zoukankan      html  css  js  c++  java
  • hdu 4714

    一个树形dp的题,又是一个涉及不深的领域  = =;

    不过在网上看到了大神用很巧的思路解决了这个题;

    大神的思路就是:

    从树的底部往上看:如果一棵子树拥有两个及以上的叶子节点,可以将这棵子树与大树分离,并且将子树化成一条直线;

    为什么这样子是最优呢?我不会证明,但我觉得这种情况可以保留最多不被删除的边;

    代码:

     1 #pragma comment(linker,"/STACK:1024000000,1024000000")
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<queue>
     5 #include<vector>
     6 #define maxn 1000005
     7 using namespace std;
     8 
     9 vector<int>ve[maxn];
    10 bool v[maxn];
    11 int ans;
    12 int dfs(int a)
    13 {
    14     v[a]=1;
    15     int l=ve[a].size(),res=0;
    16     for(int i=0; i<l; i++)
    17         if(!v[ve[a][i]])
    18             res+=dfs(ve[a][i]);
    19     if(res>=2)
    20     {
    21         if(a==1)ans+=res-2;
    22         else ans+=res-1;
    23         return 0;
    24     }
    25     else return 1;
    26 }
    27 
    28 int main()
    29 {
    30     int t,n,a,b;
    31     scanf("%d",&t);
    32     while(t--)
    33     {
    34         ans=0;
    35         scanf("%d",&n);
    36         for(int i=1; i<=n; i++)
    37             ve[i].clear();
    38         for(int i=1; i<n; i++)
    39         {
    40             scanf("%d%d",&a,&b);
    41             ve[a].push_back(b);
    42             ve[b].push_back(a);
    43         }
    44         dfs(1);
    45         printf("%d
    ",2*ans+1);
    46         memset(v,0,sizeof v);
    47     }
    48     return 0;
    49 }
    View Code

    利用dp的思想:将整棵树拆成N个单枝(所有点的度小于2),所需的cost即为2*N-1(拆成N个单枝需 N-1 cost,合成一个环需要 N cost)。

      可用树形DP求出N最小的情况,用dp[i][j]表示以i为根的可用度为j的最小单枝数。
    状态转移方程:dp[root][0]=min(dp[root][0]+dp[son][0],dp[root][1]+dp[son][1]-1)
           dp[root][1]=min(dp[root][1]+dp[son][0],dp[root][2]+dp[son][1]-1)
           dp[root][2]=dp[root][2]+dp[son][0]
    代码:
     1 #pragma comment(linker,"/STACK:1024000000,1024000000")
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<queue>
     5 #include<vector>
     6 #define maxn 1000005
     7 using namespace std;
     8 
     9 vector<int>ve[maxn];
    10 bool v[maxn];
    11 int dp[maxn][3];
    12 int ans;
    13 
    14 void dfs(int a)
    15 {
    16     v[a]=1;
    17     dp[a][0]=dp[a][1]=dp[a][2]=1;
    18     int l=ve[a].size();
    19     for(int i=0;i<l;i++)
    20     {
    21         int u=ve[a][i];
    22         if(!v[u])
    23         {
    24             dfs(u);
    25             dp[a][0]=min(dp[a][0]+dp[u][0],dp[a][1]+dp[u][1]-1);
    26             dp[a][1]=min(dp[a][1]+dp[u][0],dp[a][2]+dp[u][1]-1);
    27             dp[a][2]=dp[a][2]+dp[u][0];
    28         }
    29     }
    30 }
    31 
    32 int main()
    33 {
    34     int t,n,a,b;
    35     scanf("%d",&t);
    36     while(t--)
    37     {
    38         memset(dp,0,sizeof dp);
    39         ans=0;
    40         scanf("%d",&n);
    41         for(int i=1; i<=n; i++)
    42             ve[i].clear();
    43         for(int i=1; i<n; i++)
    44         {
    45             scanf("%d%d",&a,&b);
    46             ve[a].push_back(b);
    47             ve[b].push_back(a);
    48         }
    49         dfs(1);
    50         ans=min(dp[1][0],min(dp[1][1],dp[1][2]));
    51         printf("%d
    ",2*ans-1);
    52         memset(v,0,sizeof v);
    53     }
    54     return 0;
    55 }
    View Code
  • 相关阅读:
    USACO3.2.5Magic Squares
    USACO3.1.4Shaping Regions
    USACO3.2.3Spinning Wheels
    USACO3.1.3Humble Numbers
    USACO3.1.6Stamps
    USACO3.1.1AgriNet
    USACO3.3.5A Game
    USACO3.2.4Feed Ratios
    USACO3.2.2Stringsobits
    USACO3.2.6Sweet Butter
  • 原文地址:https://www.cnblogs.com/yours1103/p/3324286.html
Copyright © 2011-2022 走看看