• HDOJ树形DP专题之Tree Cutting


    题目大意:给定一棵树,求移除树中哪些结点后,剩下的结点最多的连通支的结点数目不超过原树总结点的一半。

    分析:先用dfs将无根树转为有根树,在一棵有根树中,去掉某个结点后,剩余的分支为儿子结点所在的分支和父亲结点所在的分支,取结点数目最多的一支即可。

    View Code
     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <vector>
     4 #define N 10000
     5 #define MAX(a,b) ((a)>(b)?(a):(b))
     6 using namespace std;
     7 vector<int> g[N],dep[N];
     8 int p[N],d[N],cnt[N],sum[N],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   dep[d[u]].push_back(u);
    15   for(i=0;i<g[u].size();i++)
    16   {
    17     v=g[u][i];
    18     if(v!=fa) dfs(v,p[v]=u);
    19   }
    20 }
    21 void dp()
    22 {
    23   int i,j,v;
    24   memset(sum,0,sizeof(sum));
    25   memset(cnt,0,sizeof(cnt));
    26   for(i=dmax;i>=0;i--)
    27   {
    28     for(j=0;j<dep[i].size();j++)
    29     {
    30       v=dep[i][j];
    31       sum[v]+=1;
    32       cnt[v]=MAX(cnt[v],n-sum[v]);
    33       if(i) sum[p[v]]+=sum[v],cnt[p[v]]=MAX(cnt[p[v]],sum[v]);
    34     }
    35   }
    36 }
    37 int main()
    38 {
    39   int i,u,v,f;
    40   while(~scanf("%d",&n))
    41   {
    42     for(i=0;i<n;i++)  g[i].clear(),dep[i].clear();
    43     for(i=1;i<n;i++)
    44     {
    45       scanf("%d%d",&u,&v),u--,v--;
    46       g[u].push_back(v);
    47       g[v].push_back(u);
    48     }
    49     p[0]=-1;
    50     dmax=0;
    51     dfs(0,-1);
    52     dp();
    53     for(f=i=0;i<n;i++)
    54     {
    55       if(cnt[i]*2<=n) f=1,printf("%d\n",i+1);
    56     }
    57     if(!f) puts("NONE");
    58   }
    59   return 0;
    60 }
  • 相关阅读:
    Antd表格跨行
    Echarts使用记录
    PAT甲级刷题实录——1010
    PAT甲级刷题实录——1009(写文章时又想到了改进方法)
    PAT甲级刷题实录——1008
    PAT甲级刷题实录——1007
    PAT甲级刷题实录——1006
    PAT甲级刷题实录——1005
    PAT甲级刷题实录——1004
    PAT甲级刷题实录——1003
  • 原文地址:https://www.cnblogs.com/algorithms/p/2479609.html
Copyright © 2020-2023  润新知