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 }
原文地址:https://www.cnblogs.com/acSzz/p/2636097.html