hdu1520-树形dp-Anniversary party

来源:互联网 发布:角逐超高空知乎 编辑:程序博客网 时间:2024/06/04 20:06

http://acm.hdu.edu.cn/showproblem.php?pid=1520
挺经典的,转移状态的时候想简单了。。
就改了一行就对了。。
给定一个树,他的父亲节点 和儿子节点有 邻接关系,选了父亲就不能选儿子,每个点有固定的价值,问你咋选,价值最大。
我开始的状态转移思路是(每个节点存在两种状态,分别是算本身的价值和 不算本身节点(只算儿子节点)的价值)。
然后 每次 转换一次。(相当于隔着一个节点,儿子和父亲分一组)
但是这么写错了,因为不取父节点,也可以不取儿子。。如果儿子的儿子 价值更大。。
还有一点也没考虑到,就是存在多个 大boss(把每一个的花费累加)

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int maxn=1e4;int m;vector<int>p[2];vector<int>G[maxn];int v[maxn];int dp[maxn];int du[maxn];int dfs(int s,int pre){     int all=0;     int all2=0;     for(int i=0;i<G[s].size();i++){         int to=G[s][i];         if(to==pre)continue;         dfs(to,s);          all2+=max(dp[to],v[to]);//不拿父节点的,也可能不拿子节点          all+=dp[to];     }     int ans=max(all+v[s],all2);     v[s]=all+v[s];     dp[s]=all2;         return ans ;}int main(){   int a,b;    while(~scanf("%d",&m)){         memset(du,0,sizeof(du));         for(int i=0;i<2;i++)            p[i].clear();         memset(du,0,sizeof(du));         memset(dp,0,sizeof(dp));         for(int i=0;i<maxn;i++)             G[i].clear();         for(int i=1;i<=m;i++)             scanf("%d",&v[i]);         while(~scanf("%d%d",&a,&b)){             if(!a&&!b) break;             G[b].push_back(a);             G[a].push_back(b);             du[a]++;         }         int ans=0;            for(int i=1;i<=m;i++){                if(du[i]==0)                ans+=dfs(i,-1);            }         printf("%d\n",ans);   }    return 0;}
原创粉丝点击