入门的树形dp,定义dp[i][1/0],1为取当前结点的权值,0为不取
状态转移方程:
dp[to][1] += max(0, dp[it][0]);
dp[to][0] += max(dp[it][0], dp[it][1]);其中to为当前子树父结点,it为to的子结点
第一道树形dp,纪念一下
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 6010;
int dp[N][2], val[N], vis[N], de[N], cnt, head[N];
struct node{
int end, next;
}ver[N];
void addedge(int a, int b){
ver[cnt].end = b;
ver[cnt].next = head[a];
head[a] = cnt++;
}
void dfs(int to){
if (head[to] == -1){
dp[to][1] = val[to];
dp[to][0] = 0;
return ;
}
for (int iit = head[to];iit != -1;iit = ver[iit].next){
int it = ver[iit].end;
if (vis[it])
continue;
vis[it] = 1;
dfs(it);
dp[to][1] += max(0, dp[it][0]);
dp[to][0] += max(dp[it][0], dp[it][1]);
}
dp[to][1] += max(0, val[to]);
return ;
}
int main(){
int n, i, a, b;
while (~scanf("%d", &n)){
memset(head, -1, sizeof(head));
memset(dp, 0, sizeof(dp));
memset(de, 0, sizeof(de));
memset(vis, 0, sizeof(vis));
cnt = 0;
for (i = 1;i <= n;i++)
scanf("%d", &val[i]);
while (scanf("%d%d", &a, &b)){
if (a == 0&&b == 0)
break;
addedge(b, a);
de[a]++;
}
for (i = 1;i <= n;i++)
if (de[i] == 0){
dfs(i);
break;
}
printf("%d\n", max(dp[i][0], dp[i][1]));
}
return 0;
}