標籤: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 intint 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;}