poj 1655 Balancing Act(求树的重心)

 

poj 1655 Balancing Act(求树的重心)

分类: dp   106人阅读  评论(0)  收藏  举报

在一棵树中,去掉一个点,使得剩下的每一颗树的结点数最多的那颗树,结点数最少。

具体解法看注释.


[html]  view plain copy
  1. /*  
  2.     定义dp[i]为去掉i结点,剩下的树里,结点最多的那颗树的结点数。  
  3.     可分为2类情况。  
  4.     1、由于i结点的儿子结点都成了一棵树的根节点,所以dp[i] = (i的每个儿子所拥有的结点数,的最大值)。  
  5.     2、而另一种情况就是剩下的那棵树,所以dp[i] = N-num[i]。  
  6.     其中num[i]表示以i为根的树的所有结点数,可以dfs求出。  
  7. */  
  8. #include<cstdio>  
  9. #include<algorithm>  
  10. #include<cstring>  
  11. #include<vector>  
  12. using namespace std;  
  13. #define MAXN 20005  
  14. int N;  
  15. vector<int> node[20005];  
  16. int num[MAXN];  
  17. int dp[MAXN];  
  18. bool vis[MAXN]; //由于为无向图,所以用这个来标记此结点是否计算过。  
  19.   
  20. int dfs(int id)  
  21. {  
  22.     int n=node[id].size();  
  23.     vis[id]=1;  
  24.     num[id]=1;  
  25.     for(int i=0;i<n;i++)  
  26.     {  
  27.         if(!vis[node[id][i]])  
  28.         num[id]+=dfs(node[id][i]);  
  29.     }  
  30.     return num[id];  
  31. }  
  32. void cal(int id)  
  33. {  
  34.     int n=node[id].size();  
  35.     int k;  
  36.     vis[id]=1;  
  37.     for(int i=0;i<n;i++)  
  38.     {  
  39.         k=node[id][i];  
  40.         if(vis[k])    //只有可能是它老爸  
  41.         {  
  42.             dp[id]=max(dp[id],N-num[id]);  
  43.         }  
  44.         else          //它儿子  
  45.         {  
  46.             dp[id]=max(dp[id],num[k]);  
  47.             cal(k);  
  48.         }  
  49.     }  
  50. }  
  51. int main()  
  52. {  
  53.     int t,a,b;  
  54.     scanf("%d",&t);  
  55.     while(t--)  
  56.     {  
  57.         scanf("%d",&N);  
  58.         for(int i=1;i<=N;i++)  
  59.             node[i].clear();  
  60.         memset(dp,0,sizeof(dp));  
  61.         for(int i=1;i<N;i++)  
  62.         {  
  63.             scanf("%d%d",&a,&b);  
  64.             node[a].push_back(b);  
  65.             node[b].push_back(a);  
  66.         }  
  67.         memset(vis,0,sizeof(vis));  
  68.         dfs(1);  
  69.         memset(vis,0,sizeof(vis));  
  70.         cal(1);  
  71.         int ans=0x7fffffff;  
  72.         int k;  
  73.         for(int i=1;i<=N;i++)  
  74.         {  
  75.             if(dp[i]<ans)  
  76.             {  
  77.                 ans=dp[i];  
  78.                 k=i;  
  79.             }  
  80.         }  
  81.         printf("%d %d\n",k,ans);  
  82.     }  
  83.     return 0;  
  84. }  

你可能感兴趣的:(dp)