//树形DP,TREE DP。这里使用邻接表存储树,可以改进的一点就是使用动态分配数组。 #include<stdio.h> #include<stdlib.h> #include<string.h> int f[20001]; int n; //树的节点的表示 typedef struct node { int num; struct node *next; }; //建立头结点数组 node ft[20001]; //深度优先搜索,last用于指示上一层节点编号,主要是防止死循环 int dfs(int last,int p) { int max=0,sum=1,k,s; node *t=ft[p].next; if(last>0&&t->next==NULL) { f[p]=n-1; return 1; } else { //循环搜索p节点的每一棵子树 while(t!=NULL) { if(t->num!=last) { k=dfs(p,t->num); sum+=k; if(k>max) max=k; } t=t->next; } //状态转移方程:求每一棵子树所具有的节点数目和除去当前节点及子节点外剩下 //节点的数目,求出最大值即为当前节点的balanc值 f[p]=max>n-sum?max:n-sum; } return sum; } int main() { int cas; scanf("%d",&cas); while(cas--) { int i,j,a,b,min=30000; scanf("%d",&n); memset(f,0,sizeof(f)); //初始化头结点 for(i=1;i<=n;i++) ft[i].next=NULL; //存储每一个节点,并建立邻接表 for(i=1;i<n;i++) { scanf("%d%d",&a,&b); node *t1,*t2; t1=(node *)malloc(sizeof(node)); t2=(node *)malloc(sizeof(node)); t1->num=b;t1->next=ft[a].next; ft[a].next=t1; t2->num=a;t2->next=ft[b].next; ft[b].next=t2; } //深度遍历树 dfs(0,1); //寻找balance的最小值 for(i=1;i<=n;i++) { if(f[i]<min) { min=f[i]; a=i; } } printf("%d %d/n",a,min); } return 0; }
从网上搜索到的用STL写的,学习一下
#include <iostream> #include <vector> using namespace std; vector<int>v[20001]; int n,dp[20001]; int dfs(int x,int y) { int k=0,i,t,val=1; if(x>0&&v[y].size()==1) { dp[y]=n-1; return 1; } for(i=0;i<v[y].size();i++) if(v[y][i]!=x) { t=dfs(y,v[y][i]); if(t>k) k=t; val+=t; } dp[y]=(n-val)>k?(n-val):k; return val; } int main() { int t;scanf("%d",&t); while(t--) { scanf("%d",&n); int i,j,a,b; memset(dp,0,sizeof(dp)); for(i=1;i<=n;i++) v[i].clear(); for(i=1;i<n;i++) { scanf("%d%d",&a,&b); v[a].push_back(b); v[b].push_back(a); } dfs(0,1); for(i=2,j=1;i<=n;i++) if(dp[i]<dp[j]) j=i; printf("%d %d/n",j,dp[j]); } return 0; }