题目大意:给定一棵树,树的每个结点有一个权值,每个结点的权值=去掉该结点后剩余的分支中结点最多的那个分支的结点数。求树中权值最小的结点。
这题CE了两次,第一次因为使用了memset没包含头文件,第二次是因为GNU C++没有头文件<memory.h>,使用<string.h>就AC了。
View Code
1 #include <stdio.h> 2 #include <string.h> 3 #include <vector> 4 #define N 20000 5 #define MAX(a,b) ((a)>(b)?(a):(b)) 6 using namespace std; 7 vector<int> g[N]; 8 int n,p[N],d[N],sum[N],w[N],dmax; 9 void dfs(int u,int fa) 10 { 11 int i,v; 12 d[u]=(fa==-1?0:d[fa]+1); 13 dmax=MAX(dmax,d[u]); 14 for(i=0;i<g[u].size();i++) 15 { 16 v=g[u][i]; 17 if(v!=fa) dfs(v,p[v]=u); 18 } 19 } 20 void dp() 21 { 22 int i,j; 23 memset(w,0,sizeof(w)); 24 for(i=0;i<n;i++) sum[i]=1; 25 for(i=dmax;i>=0;i--) 26 { 27 for(j=0;j<n;j++) 28 { 29 if(d[j]!=i) continue; 30 w[j]=MAX(w[j],n-sum[j]); 31 if(i>0) w[p[j]]=MAX(w[p[j]],sum[j]),sum[p[j]]+=sum[j]; 32 } 33 } 34 } 35 int main() 36 { 37 int i,t,u,v,min; 38 scanf("%d",&t); 39 while(t--) 40 { 41 scanf("%d",&n); 42 for(i=0;i<n;i++) g[i].clear(); 43 for(i=0;i<n-1;i++) 44 { 45 scanf("%d%d",&u,&v); 46 u--,v--; 47 g[u].push_back(v); 48 g[v].push_back(u); 49 } 50 dmax=0; 51 dfs(0,-1); 52 dp(); 53 min=0x7fffffff; 54 for(i=0;i<n;i++) if(w[i]<min) min=w[u=i]; 55 printf("%d %d\n",u+1,min); 56 } 57 return 0; 58 }