标签:
Description
Input
Output
Sample Input
7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5 0 0
Sample Output
5
题意:
n个人(编号1-N),然后n行分表代表第n个人的活跃度,之后若干行 L 和 K(0 0结束),代表K是L的上司,
问一个聚会中邀请这n个人中的若干,其中不能含直接的上下级关系,可以使聚会中的活跃度最大为多少。
状态转移:
dp[c][1]+=dp[t][0]; //c去,则t必不能去
上司不去,下级去或者不去:
dp[c][0]+=max(dp[t][0],dp[t][1]); //c不去,取t去或不去的最大值
和深搜很像,也就是用的深搜。
#include<stdio.h> #include<string.h> #include<vector> #include<algorithm> using namespace std; vector<int>g[10001]; int dp[10001][3],root[10001]; void dfs(int c) { int i,t; for(i=0;i<(int)g[c].size();i++) { t=g[c][i];//节点的孩子 dfs(t);//把孩子作为节点再搜索它的孩子 dp[c][1]+=dp[t][0];//如果双亲去,孩子就不能去 dp[c][0]+=max(dp[t][0],dp[t][1]);//如果双亲不去,就选择孩子中欢乐值大的去 } } int main() { int n,i,a,b; while(scanf("%d",&n)!=EOF) { memset(dp,0,sizeof(dp)); for(i=1;i<=n;i++) { scanf("%d",&dp[i][1]);//输入第i个人的活跃度 root[i]=i;//初始化每个节点都是根节点,也是并查集的初始化 g[i].clear();//清空容器 } while(scanf("%d%d",&a,&b)&&a+b) { g[b].push_back(a);//把数据存入容器中 root[a]=b; //a的根节点为b } int beg; for(i=1;i<=n;i++) if(root[i]==i)//如果根节点是本身,说明就是树的根节点 { beg=i; break; } dfs(beg);//搜索这棵树 printf("%d\n",max(dp[beg][0],dp[beg][1]));//输出最终的欢乐值 } return 0; }
AYITACM2016省赛第三周 L - Anniversary party(树形dp)
标签:
原文地址:http://blog.csdn.net/linyuxilu/article/details/51331464