树形dp入门,可简单理解成线性dp(数塔呗) + 一点点拓扑,
手贱的去尝试#define REP 之类的,,结果玩不好被自己死坑。(vector 从 0~size-1, 自己定义成1~size TUT)不作不死多做多死...
/*
ans=max{dp[i][0],dp[i][1]}
dp[i][0]=sum(max{dp[j][0],dp[j][1]})
//如果不包括i
则其子树的最大和是不包括其孩子
//或者包括其孩子两种可能下的最大和
dp[i][1]=sum(dp[j][0]) //如果包括i,则只能是不包括其孩子的最大和
*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;
//#define MAX(a, b) (a) > (b)? (a) : (b)
#define FOR(i, n) for(int i = 1; i <= n; i++)
#define REP(i, a, b) for(int i = a; i <= b; i++)
#define REV(i, a, b) for(int i = a; i >= b; i--)
vector<int> v[6005];
int w[6005];
int n;
bool in[6005];
int dp[6005][2];
void init()
{
FOR(i, n)
v[i].clear();
memset(in, 0, sizeof(in));
memset(dp, 0, sizeof(dp));
}
void dfs(int from)
{
//printf("%d\n", from);
int x = v[from].size();
dp[from][1] = w[from];
REP(i, 0, x-1)
{
int to = v[from][i];
dfs(to);
dp[from][0] += max( dp[to][0] , dp[to][1] );
dp[from][1] += dp[to][0];
}
}
int main()
{
while(~scanf("%d", &n))
{
init();
FOR(i, n)
scanf("%d", &w[i]);
int a, b;
while(1)
{
scanf("%d%d", &a, &b);
v[b].push_back(a);
in[a]++;
if(a == b && a == 0)
break;
}
int root;
FOR(i, n)
{
if(!in[i])
{
root = i;
break;
}
}
dfs(root);
printf("%d\n", max(dp[root][0], dp[root][1]));
}
return 0;
}