

http://acm.hdu.edu.cn/showproblem.php?pid=2412
树形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 }