// hdu 5325 Crazy Bobo // // 题目大意: // // 给你一棵树,树上每个节点都有一个权值w,选择尽可能多的节点, // 这些节点相互联通,并且按照权值升序排序之后得到节点编号, // 需相邻节点之间的任意节点都要大于较小的节点。 // // 解题思路: // 对于每一对u,v,我们建一条这样的边:权值小的像权值大的连一条边。 // 这样,问题就转化为求以u最小的权值为根的子树上点集的最大值。 // dfs即可。 // // // 感悟: // // 多校的一道题目,当时并没有想出来怎么做,看了看题解,然后按照 // 自己的理解敲了一边,交一发,STACK_OVERFLOW,心想怎么可能呢? // 然后按照题解交了一发,天真的没有复制拓展栈(当时无知的我并不知道) // 交了一发还是STACK_OVERFLOW,心里就纳闷儿了,怎么可能呢?然后云集 // 了各方的题解,发现。。。要栈拓展,因为这题数据比较大,栈的空间需要 // 很大,所以要拓展栈。习得了pragma这项黑客技能,不过这是c++的,g++不可以 // 我也不太懂,只是会Ctrl + C 和 Ctrl + V,看来还是得多掌握掌握技能。 // 继续加油吧!!!FIGHTING #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <algorithm> #include <cstring> #include <iostream> #include <vector> using namespace std; const int MAX_N = 500009; vector<int> g[MAX_N]; int d[MAX_N]; int n; int w[MAX_N]; bool vis[MAX_N]; void dfs(int u){ vis[u] = 1; d[u] = 1; for (int i=0;i<g[u].size();i++){ int v = g[u][i]; if (!vis[v]){ dfs(v); } d[u] += d[v]; } } void print(){ for (int i=1;i<=n;i++){ printf("%d ",d[i]); } puts(""); } void input(){ for (int i=1;i<=n;i++){ scanf("%d",&w[i]); g[i].clear(); } for (int i = 1;i<n;i++){ int u,v; scanf("%d%d",&u,&v); if (w[u] < w[v]) g[u].push_back(v); else if (w[v] < w[u]) g[v].push_back(u); } memset(vis,0,sizeof(vis)); } void solve(){ for (int i=1;i<=n;i++){ if (!vis[i]){ dfs(i); } } int mx = 0; for (int i=1;i<=n;i++){ mx = max(mx,d[i]); } printf("%d\n",mx); //print(); } int main(){ //freopen("1.txt","r",stdin); while(scanf("%d",&n)!=EOF){ input(); solve(); } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/timelimite/article/details/47125049