标签:style blog color os io for ar div
方法:就记节点1为树的根,两次dfs,第一次求出每个节点的所有子孙再加上它自己的节点总数num[i]。第二次就算出每个节点的balance值bal[i],算的时候就比较节点i它所有子节点的num值(删掉它之后以每个它的子节点为根形成一棵新树)还有n-num[i]的值(删掉i之后它的父节点及其相关节点也形成一棵新树),最大的就是bal[i]。
注意:WA了几次是因为没有考虑边界情况(n==2),dfs写的太不熟练了,代码能力有待提高啊!
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<map> #include<set> #include<vector> #include<algorithm> #include<stack> #include<queue> using namespace std; #define INF 1000000000 #define eps 1e-8 #define pii pair<int,int> #define LL long long int int T,n,a,b,ans_i,ans; vector<int>v[20005]; int num[20005],bal[20005]; int dfs1(int i,int fa); void dfs2(int i,int fa); int main() { //freopen("in2.txt","r",stdin); //freopen("out.txt","w",stdout); scanf("%d",&T); while(T--) { ans_i=0; ans=INF; scanf("%d",&n); if(n==1) { printf("1 0\n"); } else if(n==2) { scanf("%d%d",&a,&b); printf("1 1\n"); } else { for(int i=1; i<=n; i++) { v[i].clear(); num[i]=1; bal[i]=-1; } for(int i=1; i<n; i++) { scanf("%d%d",&a,&b); v[a].push_back(b); v[b].push_back(a); } dfs1(1,-1); dfs2(1,-1); for(int i=1; i<=n; i++) { if(bal[i]<ans) { ans_i=i; ans=bal[i]; } } printf("%d %d\n",ans_i,ans); } } //fclose(stdin); //fclose(stdout); return 0; } int dfs1(int i,int fa) { /*if(v[i].size()==1) return num[i];*/ /*这句判断是不能加的,加了就是WA,个中原因非常微妙: 因为我加这句的本意是当遇到了叶子节点时,它的num就直接返回1就行了, 而叶节点的size就是1(只有父节点)。 但是我这里就忽略了一种特殊情况,那就是这棵数可能根节点的size也为1!!! 所以就在这种情况下WA了。 实际上没有必要加这一句,下面的循环语句已经可以很好的处理各个节点了。*/ //这里可以总结一条树的性质:叶节点一定含一条边,根节点可能含一条边,其它节点至少含两条边。 for(unsigned int j=0; j<v[i].size(); j++) { int &t=v[i][j]; if(t==fa) { continue; } else { num[i]+=dfs1(t,i); } } //cout<<i<<"_-_"<<num[i]<<endl; return num[i]; } void dfs2(int i,int fa) { for(unsigned int j=0; j<v[i].size(); j++) { int &t=v[i][j]; if(t==fa) { bal[i]=max(bal[i],num[1]-num[i]); } else { bal[i]=max(bal[i],num[t]); dfs2(t,i); } } //cout<<i<<"___"<<bal[i]<<endl; }
poj1655(dfs,树形dp),布布扣,bubuko.com
标签:style blog color os io for ar div
原文地址:http://www.cnblogs.com/zywscq/p/3898490.html