题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5325
#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
const int maxn =500005;
using namespace std;/*
题目大意:给定一棵树,
你可以在树中找一个联通快,
问其联通快的最大大小是多少,
条件是:把联通块中的所有权重排序,
然后按序扫描的过程中的两点之间的路径的点
的权值均比出发的点小。联通块的条件本质上可以理解为:
只能在已经走过的点进行扩展,
那么手动模拟一会儿后就可以看到,
稍微简单点的情况,一个点为中心扩展开来的,
每条分支上的数字都是递增的,
这样就是说每次跳跃都经过的是走过的点,
可以保证符合题意,但其实这种状态可以扩展,
在每个分支上其实还可以有分叉,也是可以以一个最小的为中心,
就是以多个最小的为一条链。这样树形DP的思维就稍微有点了,
对每个子节点,我们维护比当前节点权重值小的子节点的DP值来更新当前节点的DP值,
然后在比当前节点大的子节点中用之前计算好的DP值去向下更新。*/int val[maxn],n;
int dp[maxn];
int x,y;///容器存储边
vector<int> g[maxn];
int ans=0;
void dfs(int u,int pre,int len)///当前的权重和维护出来的大小
{dp[u]=len+1;for(int i=0;i<g[u].size();i++){int v=g[u][i],tmp=len;if(v==pre) continue;if(val[u]>val[v]) continue;dfs(v,u,0);dp[u]+=dp[v];}for(int i=0;i<g[u].size();i++){int v=g[u][i];if(v==pre) continue;if(val[v]>val[u]) continue;dfs(v,u,dp[u]);}
}int main()
{while(scanf("%d",&n)==1){///init();for(int i=1;i<=n;i++) scanf("%d",&val[i]),g[i].clear();for(int i=1;i<n;i++){scanf("%d%d",&x,&y);g[x].push_back(y);g[y].push_back(x);}memset(dp,0,sizeof(dp));dfs(1,-1,0);ans=0;for(int i=1;i<=n;i++) ans=max(ans,dp[i]);printf("%d\n",ans);}return 0;
}