zoukankan      html  css  js  c++  java
  • hdu 2412 树形dp

     1 /*
     2 题目大意:一个n个节点的树,求选取一些节点(不能含有父子关系的)的最大数量,且是否唯一。
     3 dp(i,0)表示当前节点i不选,dp(i,1)表示当前节点i选
     4 叶子节点dp(i,0)=0,dp(i,1)=1
     5 dp(i,0)=sigma(max(dp(j,0),dp(j,1))) (j是i的儿子)
     6 dp(i,1)=sigma(dp(j,0))+1(j是i的儿子)
     7 最多人数为max(dp(0,0),dp(0,1))(0表示根节点)
     8 用flag数组标记结果是否唯一
     9 对于叶子结点, flag[k][0]=flag[k][1] = 1.
    10 对于非叶子结点,
    11 不选i,对于i的任一儿子j,
    12 若(dp[j][0] > dp[j][1] 且 flag[j][0] == 0) 或 (dp[j][0] < dp[j][1] 且 flag[j][1] == 0) 或 (dp[j][0] == dp[j][1]),
    13 则flag[i][0] = 0
    14 选i,对于i的任一儿子j有flag[j][0] = 0, 
    15 则flag[i][1] = 0
    16 */
    17 #pragma warning (disable:4786)
    18 #include <iostream>
    19 #include <cstring>
    20 #include <cstdio>
    21 #include <string>
    22 #include <map>
    23 #include <vector>
    24 using namespace std;
    25 
    26 const int maxn=205;
    27 vector<int> f[maxn];//关系图
    28 bool flag[maxn][2];//标记是否唯一
    29 map<string,int> m;//名字与节点标号映射
    30 int dp[maxn][2];
    31 inline int max(int a,int b){return a>b?a:b;}
    32 
    33 void dfs(int id)
    34 {
    35     if(f[id].size()==0)
    36     {
    37         dp[id][0]=0;dp[id][1]=1;
    38         return ;
    39     }
    40     int i,sum1=0,sum2=0;
    41     for(i=0;i<f[id].size();i++)
    42     {
    43         dfs(f[id][i]);
    44         sum1+=max(dp[f[id][i]][0],dp[f[id][i]][1]);
    45         sum2+=dp[f[id][i]][0];
    46         if((dp[f[id][i]][0]>dp[f[id][i]][1] && flag[f[id][i]][0]==0) 
    47         || (dp[f[id][i]][0]<dp[f[id][i]][1] && flag[f[id][i]][1]==0)
    48         || dp[f[id][i]][0]==dp[f[id][i]][1])
    49             flag[id][0]=0;
    50         if(flag[f[id][i]][0]==0)
    51             flag[id][1]=0;
    52     }
    53     dp[id][0]=sum1;dp[id][1]=sum2+1;
    54     return ;
    55 }
    56 int main()
    57 {
    58     int i,n,cnt;
    59     string name1,name2;
    60     while(scanf("%d",&n),n)
    61     {
    62         for(i=1;i<maxn;i++) f[i].clear();
    63         m.clear();
    64         cnt=0;
    65         cin>>name1;m[name1]=++cnt;
    66         for(i=2;i<=n;i++)
    67         {
    68             cin>>name1>>name2;
    69             if(m.find(name1)==m.end()) 
    70                 m[name1]=++cnt;
    71             if(m.find(name2)==m.end()) 
    72                 m[name2]=++cnt;
    73             f[m[name2]].push_back(m[name1]);
    74         }
    75         memset(flag,1,sizeof(flag));
    76         dfs(1);
    77         int ans=max(dp[1][0],dp[1][1]);
    78         printf("%d ",ans);
    79         if(dp[1][0]==dp[1][1] || (dp[1][0]>dp[1][1] && flag[1][0]==0) || (dp[1][0]<dp[1][1] && flag[1][1]==0))
    80             printf("No
    ");
    81         else printf("Yes
    ");
    82     }
    83     return 0;
    84 }
  • 相关阅读:
    Find the Smallest K Elements in an Array
    Count of Smaller Number
    Number of Inversion Couple
    Delete False Elements
    Sort Array
    Tree Diameter
    Segment Tree Implementation
    Java Programming Mock Tests
    zz Morris Traversal方法遍历二叉树(非递归,不用栈,O(1)空间)
    Algorithm about SubArrays & SubStrings
  • 原文地址:https://www.cnblogs.com/xiong-/p/4136010.html
Copyright © 2011-2022 走看看