题解:
根据题意可以知道每个点都有可取可不取,所以我们设 dp[i][j] (i 表示第 i 个点,j:0/1 表示取这个人或者不取)。
可以推得公式:
dp[u][0] += max(dp[v][1], dp[v][0]) ,dp[u][1] += dp[v][0]。
然后跑从度为 0 的点跑dfs即可。
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <stack>
#include <cmath>
#include <deque>
#include <queue>
#include <list>
#include <set>
#include <map>
#define line printf("---------------------------\n")
#define mem(a, b) memset(a, b, sizeof(a))
#define pi acos(-1)
using namespace std;
typedef long long ll;
const double eps = 1e-9;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const int maxn = 6000+10;
vector<int> edge[maxn];
int happy[maxn], dp[maxn][2], du[maxn];
void dfs(int u, int father) {
dp[u][1] = happy[u];
for(int i = 0; i < edge[u].size(); i++) {
int v = edge[u][i];
dfs(v, u);
dp[u][1] += dp[v][0];
dp[u][0] += max(dp[v][0], dp[v][1]);
}
}
int main() {
int n;
while(~scanf("%d", &n)) {
for(int i = 1; i <= n; i++) {
edge[i].clear();
du[i] = dp[i][0] = dp[i][1] = 0;
scanf("%d", &happy[i]);
}
int u, v;
while(scanf("%d %d", &v, &u), u && v) {
edge[u].push_back(v);
du[v]++;
}
int s;
for(int i = 1; i <= n; i++) {
if(!du[i]) {
s = i;
break;
}
}
dfs(s, -1);
printf("%d\n", max(dp[s][0], dp[s][1]));
}
}