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; }