题目 >>http://codevs.cn/problem/1380/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN = 2e5;
bool used[MAXN];
int n,a,b,num[MAXN],s,firs[MAXN],ans,nex[MAXN],dp[MAXN][2],cnt = 0;
struct zt
{
int f,t;
}road[MAXN];
void build(int f,int t)
{
road[++cnt] = (zt){f,t};
nex[cnt] = firs[f];
firs[f] = cnt;
}
int dfs(int x,int d) //表示x 去(d == 1)还是不去(d == 0)。
{
int ans = 0;
for(int i = firs[x];i != -1; i = nex[i])
{
int v = road[i].t;
if(!dp[v][0])
dp[v][0] = dfs(v,0); // 记忆化,表示该状态下dp[编号][去与否]的最大值
if(!dp[v][1])
dp[v][1] = dfs(v,1);
if(d)
ans += dp[v][0]; //上司去。
else
ans += max(dp[v][0],dp[v][1]);//上司不去,若其下有更优解他也可能不去。
}
if(d)
return ans + num[x];//x 若去要加上他自己。
return ans;
}
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n; i++)
scanf("%d",&num[i]),firs[i] = -1;
for(int i = 1;i < n; i++)
{
scanf("%d%d",&a,&b);
build(b,a); // 建立上下级关系的图
used[a] = 1;
}
scanf("%d%d",&a,&b);
for(int i = 1;i <= n;i ++)
if(!used[i])
{
s = i; //找到大boss(根节点)。
break;
}
ans = max(dfs(s,0),dfs(s,1)); // 分别计算大boss去还是不去。
printf("%d",ans);
}