Description
Input
Output
Sample Input
7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5 0 0
Sample Output
5
关于输入输出:
输入:
输入n个结点,接下去的n行,表示1-n的每个结点分别具有的活跃值,在接下来去的n-1行,输入a,b,表示b是a的上司
输出:
由于直接有上司和下属关系的两个人不能同时参加party, 求出能让party活跃值最大的方案(求出最大的活跃值即可).
题目的图形:
解题思路:
每个结点有两种状态,参加和不参加,用0表示不参加,1表示参加
dp[i][1]表示第i个参与者参加了,dp[i][0]表示第i个参与者没有参加。
状态转移方程:dp[u][0] += max (dp[v][0], dp[v][1]) :表示上司没参加,其员工可以参加可以不参加
dp[u][1] += dp[v][0] : 表示若上司参加了,其员工一定不会参加
树形dp建树:
用连接表,这是一个有向树
代码:
#include <cstdio> #include <cmath> #include <string> #include <cstring> #include <iostream> using namespace std; #define N 6005 int dp[N][2], val[N], visit[N]; int in[N]; struct node { int v; int next; }pe[N<<1]; int e, head[N]; void init () { memset (head, -1, sizeof (head)); e = 0; } void addedge (int u, int v) { pe[e].v = v; pe[e].next = head[u]; head[u] = e ++; } int dfs (int u) { visit[u] = 1; dp[u][0] = 0; dp[u][1] = val[u]; for (int i = head[u]; i != -1; i = pe[i].next) { int v = pe[i].v; dfs(v); dp[u][0] += max(dp[v][0], dp[v][1]); dp[u][1] += dp[v][0]; } return max(dp[u][0], dp[u][1]); } int main() { int n, v, u; while (scanf ("%d", &n) != EOF) { init(); for (int i = 1; i <= n; ++i) { in[i] = 0; visit[i] = 0; scanf ("%d", &val[i]); } while (scanf ("%d%d", &v, &u) && v + u != 0) { addedge (u, v); in[v]++; } int ans = 0; for (int i = 1; i <= n; ++i) { if(!in[i]) ans += dfs(i); } printf("%d\n", ans); } return 0; }