hdu 2412 Party at Hali-Bula (树形 dp)

     hdu 2412 Party at Hali-Bula (树形 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 }

 

你可能感兴趣的:(part)