hdu 1520 树形dp

来源:互联网 发布:淘宝详情页思路 编辑:程序博客网 时间:2024/06/07 05:46

题目:点击打开链接

题意:每个节点有权值,子节点和父节点不能同时选,问最后能选的最大价值是多少?

分析:这题一看到首先想到的是贪心,就是选间隔的层次的点,可是仔细想想这样是不对的,假如说选了第一层,那么肯定不能选第二层,那么这时候选第三层一定是最优的吗?显然不对,有可能不选第三层而选第四层,所以思路逐渐地清晰。用f[i][0]表示没选这个点,f[i][1]表示选了这个点,那么状态战役方程就很明显了:

 f[u][0]+=max(f[v][0],f[v][1]);//其中u是v的父节点,没选u,对于v来说可选可不选 f[u][1]+=f[v][0];   //选了u,对于v来说一定不选

有了状态转移方程,dfs从叶子向根转移,最后就求出整棵树的最大值了。

#include <cstdio>#include <cmath>#include <string>#include <cstring>#include <iostream>using namespace std;const int N=6005;struct edge{    int v;    int next;}e[N<<1];int head[N];int f[N][2];int val[N],in[N];//节点权值,节点入度int cnt;void init(){    memset(in,0,sizeof(in));    memset(head,-1,sizeof(head));    cnt=0;}void add_edge(int u,int v) //建立有向图u->v{    e[cnt].v=v;    e[cnt].next=head[u];    head[u]=cnt++;}int dfs(int u){    f[u][0]=0;    f[u][1]=val[u];    for(int i=head[u];~i;i=e[i].next){        int v=e[i].v;        dfs(v);        f[u][0]+=max(f[v][0],f[v][1]);        f[u][1]+=f[v][0];    }    return max(f[u][0],f[u][1]);}int main(){    int n,v,u;    //freopen("f.txt","r",stdin);    while(~scanf("%d",&n)){        init();        for(int i=1;i<=n;i++){            scanf("%d",&val[i]);        }        while(scanf("%d%d",&v,&u)&&(v+u)){            add_edge(u,v);            in[v]++;        }        int ans=0;        for(int i=1;i<=n;i++){            if(!in[i]){                ans+=dfs(i);            }        }        printf("%d\n",ans);    }    return 0;}

还有的是建立的无向图,也可以:http://www.cnblogs.com/kuangbin/archive/2012/08/28/2659716.html  

仔细读了遍原题,It means that the supervisor relation forms a tree rooted at the rector V. E. Tretyakov. 发现这是一整棵树,所以只有一个树根,只找到树根dfs一遍就可以了,用vector就挺简单的。

#include<stdio.h>#include<string.h>#include<iostream>#include<vector>#include<algorithm>using namespace std;const int MAXN=6050;vector<int>vec[MAXN];int f[MAXN];int hap[MAXN];int dp[MAXN][2];void dfs(int root){    int len=vec[root].size();    dp[root][1]=hap[root];//    for(int i=0;i<len;i++)//       dfs(vec[root][i]);    for(int i=0;i<len;i++)    {        dfs(vec[root][i]);        dp[root][0]+=max(dp[vec[root][i]][1],dp[vec[root][i]][0]);        dp[root][1]+=dp[vec[root][i]][0];    }}int main(){   // freopen("f.txt","r",stdin);    //freopen("out.txt","w",stdout);    int n;    int a,b;    while(scanf("%d",&n)!=EOF)    {        for(int i=1;i<=n;i++)        {            scanf("%d",&hap[i]);            vec[i].clear();            f[i]=-1;//树根标记            dp[i][0]=dp[i][1]=0;        }        while(scanf("%d%d",&a,&b))        {            if(a==0&&b==0)break;            f[a]=b;            vec[b].push_back(a);        }        a=1;        while(f[a]!=-1)a=f[a];//找到树根        dfs(a);        printf("%d\n",max(dp[a][1],dp[a][0]));    }    return 0;}


0 0
原创粉丝点击