一群人参加聚会,但是每个人都不想和老板一起参加,问最可以多少人参加。
状态方程简单:
dp[i][0] += max { dp[j][1] , dp[j][0] }
dp[i][1] += dp[i][0];
判断唯一性有点难想,加一个状态opt[i][2]
判断是哪个状态转移过来的,然后根据转移过来的状态来判断现在状态。
注意了 dp[v][1]==dp[v][0] 是关键点,多解的源头就在这里。
#include<iostream> #include<algorithm> #include<stdlib.h> #include<string.h> #include<stdio.h> #include<math.h> #include<string> #include<vector> #include<queue> #include<list> #include<map> using namespace std; typedef long long lld; typedef unsigned int ud; #define oo 0x3f3f3f3f #define maxn 205 int dp[maxn][2]; int opt[maxn][2]; int father[maxn]; int n; vector<int> G[maxn]; map<string, int> mat; void tree_dp(int u) { dp[u][0] = 0; dp[u][1] = 1; opt[u][0] = 1; opt[u][1] = 1; for (int i = 0; i < G[u].size(); i++) { int v = G[u][i]; tree_dp(v); dp[u][1] += dp[v][0]; dp[u][0] += max(dp[v][0], dp[v][1]); if (dp[v][0] > dp[v][1] && opt[v][0] == 0) opt[u][0] = 0; if (dp[v][1] > dp[v][0] && opt[v][1] == 0) opt[u][0] = 0; if (dp[v][1] == dp[v][0]) opt[u][0] = 0; if (opt[v][0] == 0) opt[u][1] = 0; } } int main() { char str[102], ss[102]; int u, v, root, cnt; while (scanf("%d",&n) && n) { memset(dp, 0, sizeof dp); mat.clear(); for (int i = 1; i <= n; i++) G[i].clear(); root = 1; cnt = 0; scanf("%s", str); mat[str] = ++cnt; for (int i = 1; i <= n - 1; i++) { scanf("%s %s", str, ss); if (!mat[str]) mat[str] = ++cnt; if (!mat[ss]) mat[ss] = ++cnt; G[mat[ss]].push_back(mat[str]); } tree_dp(root); if (dp[root][1] > dp[root][0] && opt[root][1] == 1) printf("%d Yes\n", dp[root][1]); else if (dp[root][0] > dp[root][1] && opt[root][0] == 1) printf("%d Yes\n", dp[root][0]); else printf("%d No\n", max(dp[root][0], dp[root][1])); } return 0; }