hdu 4276 树形dp背包

来源:互联网 发布:深渊巨口皮肤淘宝 编辑:程序博客网 时间:2024/05/22 07:56

题意:n个点,n-1条边,每条边有权值,每个点有价值 ,问你能否在T时间内从1走到n,如果能,获得的最大价值。

       先用spfa求出1至n的最短路径,并且将1到n最短路径上的边权致零,t减去dis【n】这样以后就可以不用考虑怎样回到n了,就和普通的树形dp一样,

状态方程   dp [ u ] [ j ] = max ( dp [ u ][ j ]  ,dp[ v] [k ] +   dp [u ] [j-k-w ] ); w为边权,v是u的子节点。

#include<cstdio>#include<cstring>#include<queue>#include<iostream>using namespace std;#define FF  freopen("Input.txt","r",stdin)#define mem(x,y) memset(x,y,sizeof(x))#define ll long long#define inf 1000020const int N=120;struct Graph{    int head[N*2],val[N*2],to[N*2],next[N*2],tot;    void init()    {        tot=0;        mem(head,-1);    }    void add(int u,int v,int w)    {        to[tot]=v;        val[tot]=w;        next[tot]=head[u];        head[u]=tot++;    }}G;int num[110],p[110],pre[110],vis[110],dis[110];int dp[110][505],n,t;void spfa(int u){    int i;    for(i=1;i<=n;i++) dis[i]=inf;    dis[u]=0;    queue<int>Q;    Q.push(u);    mem(vis,0);    vis[u]=1;    while(!Q.empty())    {        u=Q.front();Q.pop();        vis[u]=0;        for(i=G.head[u];i!=-1;i=G.next[i])        {            int v=G.to[i];            int w=G.val[i];            if(dis[v]>dis[u]+w)            {                pre[v]=u;                p[v]=i;                dis[v]=dis[u]+w;                if(!vis[v])                {                    vis[v]=1;                    Q.push(v);                }            }        }    }    for(i=n;i!=1;i=pre[i])    {        G.val[p[i]]=0;        G.val[p[i]^1]=0;    }}void dfs(int u,int f){    int i,j,k;    for(i=0;i<=t;i++) dp[u][i]+=num[u];    for(i=G.head[u];i!=-1;i=G.next[i])    {        int v=G.to[i],w=G.val[i]*2;        if(v==f) continue;        dfs(v,u);        for(j=t;j>=w;j--)           for(k=0;j-k>=w;k++)             dp[u][j]=max(dp[u][j],dp[v][k]+dp[u][j-k-w]);    }}int main(){    //FF;    int i;    while(~scanf("%d%d",&n,&t))    {        int u,v,w;        G.init();        for(i=1;i<n;i++)        {            scanf("%d%d%d",&u,&v,&w);            G.add(u,v,w);G.add(v,u,w);        }        for(i=1;i<=n;i++)           scanf("%d",&num[i]);        spfa(1);        if(t<dis[n]) { printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n");continue;}        t=t-dis[n];        mem(dp,0);        dfs(1,0);        printf("%d\n",dp[1][t]);    }    return 0;}


原创粉丝点击