HLG1475国王的宴会【树形DP】
大意:
你知道国王喜欢热闹,所以你希望能邀请尽量多的人,但是做为直接上下级关系的两个人直接出现在宴会上的时候会显得很尴尬,所以不能同时请有上下级关系的两个人。
国王是宴会的主办方,也是这个王国的最高领袖,所以必须到场。
为了能为宴会准备的更好,你需要知道整个宴会最多可以邀请多少宾客。
分析 :
树形DP
dp[x][0]代表x及其子树在不选x的情况下的最优解
dp[x][1]代表x及其子树在选x的情况下的最优解
那么 dp[x][0] = sum(max(dp[y][0], dp[y][1]))
dp[x][1] = sum(dp[y][0]) + 1
由于boss一定在场 所以最终结果保留在 dp[boss][1]之中
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 const int maxn = 1005; 7 int n, m; 8 9 struct Node { 10 int to, next; 11 }e[maxn * maxn]; 12 int head[maxn]; 13 int tot; 14 void add(int u, int v) { 15 e[tot].to = v; 16 e[tot].next = head[u]; 17 head[u] = tot++; 18 } 19 int H[maxn], T[maxn]; 20 int boss; 21 22 int dp[maxn][2]; 23 24 void dfs(int u) { 25 if(H[u] == 0) { 26 dp[u][0] = 0; 27 dp[u][1] = 1; 28 return ; 29 } 30 int sum1 = 0; int sum2 = 0; 31 for(int i = head[u]; i; i = e[i].next) { 32 int v = e[i].to; 33 dfs(v); 34 sum1 += dp[v][0]; 35 sum2 += max(dp[v][0], dp[v][1]); 36 } 37 dp[u][1] = sum1 + 1; 38 dp[u][0] = sum2; 39 } 40 41 int DP() { 42 memset(dp, 0, sizeof(dp)); 43 dfs(boss); 44 return dp[boss][1]; 45 } 46 47 int main() { 48 int u, v; 49 while(EOF != scanf("%d %d",&n, &m) ) { 50 tot = 1; 51 memset(head, 0, sizeof(head)); 52 memset(H, 0, sizeof(H)); 53 memset(T, 0, sizeof(T)); 54 for(int i = 1; i <= m; i++) { 55 scanf("%d %d",&u, &v); 56 add(u, v); 57 H[u]++; T[v]++; 58 } 59 for(int i = 1; i <= n; i++) { 60 if(T[i] == 0) { 61 boss = i; 62 break; 63 } 64 } 65 printf("%d\n", DP()); 66 } 67 return 0; 68 }