题意:
公司要开一个舞会,邀请各阶层的职员来参加,每个职员来参加舞会时会给舞会增高快乐值(大小因人而异)。
但是如果一个职员的直属领导也来参加舞会,那么这个职员就不会去参加舞会。
(相当于一棵树,如果父亲在,儿子必定不在,但孙子可以在也可以不在)
题解:
树形DP,转移方程:
dp[root][i] (i=0,1)表示当前结点root,1代表root在,0代表不在。
如果父亲在,儿子必定不在
如果父亲不在,选取儿子最大值的状态。
代码:
#include <set> #include <map> #include <cmath> #include <stack> #include <queue> #include <vector> #include <string> #include <cstdio> #include <cstring> #include <sstream> #include <iomanip> #include <iostream> #include <algorithm> #define clr(str,x) memset(str,x,sizeof(str)) #define FRER() freopen("in.txt","r",stdin); #define FREW() freopen("out.txt","w",stdout); #define MAX_INF 0x7fffffff #define INF 0x3f3f3f3f #define maxn 6010 typedef long long int ll; using namespace std; int n,dp[maxn][2]; bool in[maxn]; vector<int> G[maxn]; void dfs(int root) { for(int i=0; i<G[root].size(); i++) { int v=G[root][i]; dfs(v); dp[root][1]+=dp[v][0]; dp[root][0]+=max(dp[v][0],dp[v][1]); } } int main() { //FRER(); //FREW(); int n; while(scanf("%d",&n)!=EOF) { clr(dp,0); clr(in,0); for(int i=0; i<maxn; i++) G[i].clear(); for(int i=1; i<=n; i++) { scanf("%d",&dp[i][1]); } int root=1; int u,v; while(cin>>u>>v&&(v+u)) { G[v].push_back(u); in[u]=1; } for(int i=1; i<=n; i++) { if(in[i]==0) root=i; } dfs(root); cout<<max(dp[root][0],dp[root][1])<<endl; } return 0; }