

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() == 0) return ;
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 }
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() == 0) return ;
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 }