// 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();
}
}
hdu 5325 Crazy Bobo dfs
最新推荐文章于 2018-10-14 18:03:04 发布