http://poj.org/problem?id=2342
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=17663
题意:
某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的直接上司,现在已知每个人的活跃指数和上司关系(当然不可能存在环),求邀请哪些人(多少人)来能使得晚会的总活跃指数最大。
状态是每个点的取舍。
分别可以用dp[i,1]和dp[i,0]表示第i个人来和不来。
当i来的时候,dp[i][1] += dp[j][0];//j为i的下属
当i不来的时候,dp[i][0] +=max(dp[j][1],dp[j][0]);//j为i的下属
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
typedef unsigned __int64 ull;
const double pi=acos(-1.0);
double eps=0.000001;
int max(int a,int b)
{return a<b?b:a;}
int tm[6005];
int n;
int vis[6005];
vector< vector<int > > mp(6005);
int dp[6005][2];
void dfs(int x)
{
int i;
dp[x][1]=tm[x];
dp[x][0]=0;
for (i=0;i<mp[x].size();i++)
{
int v=mp[x][i];
dfs(v);
dp[x][1]+=dp[v][0];
dp[x][0]+=max(dp[v][1],dp[v][0]);
}
}
int main()
{
cin>>n;
int i;
for (i=1;i<=n;i++)
scanf("%d",&tm[i]);
int x,y;
for (i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
mp[y].push_back(x);
vis[x]=1;
}
scanf("%d %d",&x,&y);
for (i=1;i<=n;i++)
{
if (!vis[i]) break;
}
int root=i;
dfs(root);
printf("%d\n",max(dp[root][1],dp[root][0]));
return 0;
}