zoukankan      html  css  js  c++  java
  • hdu4714 Tree2cycle 把树剪成链

    题目是问把一棵树通过剪边、加边形成一个环的最小代价。

    分成两步,先把树剪成一些链,再把链连接成一个环。

    设一棵有n个节点的树,剪掉X条边后,形成L条链。

    那么代价为X+L。

    n-1-X=edgeNum(L条链) ① //原本有n-1条边,剪掉X条,还剩edgeNum(L条链)条

    edgeNum(L条链)+L=n ② //L条链的这些边+L条边形成一个有n条边的环

    由①、②得到,L=X+1

    则代价为 X+L=2*L-1=2*X+1。

    问题转化成了,把一棵树剪成一些链,最少能剪成几条链?或者,最少需要剪掉多少条边?

    我觉得到了这一步问题就好解决了,我是树形dp搞的,求的是最少能剪成几条链。

    dp[u][0]表示u节点是所在链的端点时,以u节点为根节点的子树形成的最少的链数。

    dp[u][1]表示u节点是所在链的中间的点时,以u节点为根节点的子树形成的最少的链数。

    然后就可以转移了。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<vector>
     4 #pragma comment(linker, "/STACK:102400000,102400000")
     5 using namespace std;
     6 const int N = 1000005;
     7 const int inf = N;
     8 
     9 vector<int> G[N];
    10 int dp[N][2];
    11 
    12 inline int min(int a,int b)    {return a<b?a:b;}
    13 
    14 void dfs(int u,int fa)
    15 {
    16     int sz = G[u].size();
    17     int v,cld=0,sum=0,min1=inf,min2=inf,temp;
    18     for(int i=0;i<sz;i++)
    19     {
    20         v = G[u][i];
    21         if( v!=fa )
    22         {
    23             cld++;
    24             dfs(v,u);
    25             temp = min(dp[v][0],dp[v][1]);
    26             sum += temp;
    27             temp = dp[v][0] - temp;
    28             if( temp<min1 )    {min2=min1;min1=temp;}
    29             else if( temp<min2 )    min2=temp;
    30         }
    31     }
    32     if( !cld )    dp[u][0]=1,dp[u][1]=inf;
    33     else if( 1==cld )    dp[u][0]=sum+min1,dp[u][1]=inf;
    34     else
    35     {
    36         dp[u][0] = sum + min1;
    37         dp[u][1] = sum + min1 + min2 - 1;
    38     }
    39 }
    40 
    41 int main()
    42 {
    43     int T;
    44     int n,u,v;
    45 
    46     //freopen("4714.in","r",stdin);
    47     //freopen("myout.txt","w",stdout);
    48     scanf("%d",&T);
    49     while( T-- )
    50     {
    51         scanf("%d",&n);
    52         for(int i=1;i<=n;i++)    G[i].clear();
    53         for(int i=0;i<n-1;i++)
    54         {
    55             scanf("%d%d",&u,&v);
    56             G[u].push_back(v);
    57             G[v].push_back(u);
    58         }
    59         dfs(1,0);
    60         printf("%d
    ",2*min(dp[1][0],dp[1][1])-1);
    61     }
    62     return 0;
    63 }
    View Code
  • 相关阅读:
    02 查看线程的进程id
    ceshi
    unity atom 配置
    unity 扩展编辑器二 新建窗体
    unity 扩展编辑器一(修改编辑器名称)
    unity 计算投资回报
    Unity sendmessage发送多个参数
    unity 利用ugui 制作技能冷却效果
    unity 角色旋转
    unity 改变场景
  • 原文地址:https://www.cnblogs.com/kiwi-bird/p/3310970.html
Copyright © 2011-2022 走看看