• hdu 2412 Party at HaliBula (树形 dp)


       

     http://acm.hdu.edu.cn/showproblem.php?pid=2412

    题目大意:n个人形成一个关系树,每个节点代表一个人,节点的根表示这个人的唯一的直接上司,只有根没有上司。要求选取一部分人出来,使得每2个人之间不能有直接的上下级的关系,求最多能选多少个人出来,并且求出获得最大人数的选人方案是否唯一。

    树形dp+判断

    状态转移方程:
    对于叶子节点 dp[k][0] = 0, dp[k][1] = 1
    对于非叶子节点i,
    dp[i][0] = ∑max(dp[j][0], dp[j][1]) (j是i的儿子)
    dp[i][1] = 1 + ∑dp[j][0] (j是i的儿子) 
    最多人数即为max(dp[0][0], dp[0][1])
    如何判断最优解是否唯一
    有点难啊!!!!
    新加一个状态dup[i][j],表示相应的dp[i][j]是否是唯一方案。
    对于叶子结点, dup[k][0] = dup[k][1] = 1.
    对于非叶子结点,
    对于i的任一儿子j,若(dp[j][0] > dp[j][1] 且 dup[j][0] == 0) 或 (dp[j][0] < dp[j][1] 且 dup[j][1] == 0) 或 (dp[j][0] == dp[j][1]),则dup[i][0] = 0
    对于i的任一儿子j有dup[j][0] = 0, 则dup[i][1] = 0
     1 #include<stdio.h>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<queue>
     7 #include<set>
     8 #include<map>
     9 #define Min(a,b)  a>b?b:a
    10 #define Max(a,b)  a>b?a:b
    11 #define CL(a,num)  memset(a,num,sizeof(a));
    12 #define inf 9999999
    13 #define maxn 210
    14 #define mod 100000000
    15 #define eps  1e-6
    16 #define ll long long
    17 using namespace std;
    18 map<string ,int>map1;
    19 vector<int> g[maxn];
    20 int dp[maxn][2],dup[maxn][2];
    21 void dfs(int r)
    22 {
    23     int i , j;
    24 
    25         dp[r][0] = 0; dp[r][1] = 1;
    26         dup[r][0] = dup[r][1] = 1; // 个数唯一
    27 
    28     if(g[r].size() == 0return ;
    29 
    30    for( i = 0 ; i < g[r].size(); ++i)
    31     {
    32         int j = g[r][i] ;
    33         dfs(j);
    34         dp[r][0] += max(dp[j][0],dp[j][1]);
    35 
    36         dp[r][1] += dp[j][0] ;
    37 
    38         if(dp[j][0] > dp[j][1] && dup[j][0] == 0 ) dup[r][0] = 0;
    39         
    40         if(dp[j][1] > dp[j][0] && dup[j][1] == 0) dup[r][0] = 0;
    41         
    42         if(dp[j][0] == dp[j][1]) dup[r][0] = 0 ;
    43 
    44         if(dup[j][0] == 0) dup[r][1] = 0;
    45 
    46 
    47     }
    48 
    49 }
    50 int main()
    51 {
    52     int n,i;
    53     char c1[110] ,c2[110];
    54     while(scanf("%d",&n),n)
    55     {
    56         map1.clear();
    57         for( i =  0 ; i <= n ; ++i)g[i].clear() ;
    58         int num = 0;
    59         scanf("%s",c1);
    60         map1[c1] = ++num ;
    61         for(i = 0 ; i < n - 1;++i)
    62         {
    63             scanf("%s %s",c1,c2);
    64             if(map1.find(c1) == map1.end()) map1[c1] = ++num ;
    65             if(map1.find(c2) == map1.end()) map1[c2] = ++num ;
    66             int x = map1[c1];
    67             int y = map1[c2] ;
    68             g[y].push_back(x);
    69 
    70 
    71         }
    72         CL(dp,0);
    73         dfs(1);
    74 
    75         if(dp[1][0] > dp[1][1] && dup[1][0] == 1)printf("%d Yes\n",dp[1][0]);
    76         else if(dp[1][1] > dp[1][0] &&dup[1][1] == 1)printf("%d Yes\n",dp[1][1]);
    77         else  printf("%d No\n", max(dp[1][0],dp[1][1])) ;
    78     }
    79 }
  • 相关阅读:
    转载、收藏
    AndroidStudio 问题收集
    android4.4 添加快捷开关(以截屏为例)
    打开USB调试功能
    关于Http通信
    【原创】JMS生产者和消费者【PTP同步接收消息】
    【学习】JMS通信模式
    【原创】Unable to read TLD "META-INF/c.tld" from JAR file 解决方法
    【原创】websphere部署war包报错
    【转载】tom的RUNSTATS测试工具
  • 原文地址:https://www.cnblogs.com/acSzz/p/2636097.html
Copyright © 2020-2023  润新知