您的位置:首页 > 其它

hdu 4267 树形dp

2012-09-13 21:36 267 查看
题目:

给出一棵树,现要从树的1号节点走到n号节点,每条边都需要一定的时间才能走过,并且每个节点有相应的财宝,现在给出时间t,问能不能在时间t之内走到n节点且使得所获得的财宝最多(每个节点的财宝只能收集一次)
#include<iostream>
#include<cstdio>
#include<memory.h>
using namespace std;
int n,t,ans,a[102],dp[102][502],NE,head[102];
//dp[i][j] 表示从i 出发 花费j 时间回到i 的最大利润;
struct node
{
int u,v,next,w;
} Edge[102<<2];
void addEdge(int u,int v,int w)
{
Edge[NE].u=u;
Edge[NE].v=v;
Edge[NE].w=w;
Edge[NE].next=head[u];
head[u]=NE++;
}
int dfs1(int u,int fa)
{
if(u==n) return 1;
for(int i=head[u]; i!=-1; i=Edge[i].next)
{
int v=Edge[i].v;
if(fa!=v)
{
if(dfs1(v,u))
{
ans+=Edge[i].w;
Edge[i].w=0;
return 1;
}
}
}
return 0;
}
void dfs2(int u,int fa)
{
for(int i=head[u];i!=-1;i=Edge[i].next)
{
int v=Edge[i].v;
if(v==fa) continue;
dfs2(v,u);
int tt=Edge[i].w*2;
for(int j=t;j>=tt;j--)
{
for(int k=j-tt;k>=0;k--)
{
dp[u][j]=max(dp[u][j],dp[u][k]+dp[v][j-tt-k]);
}
}
}
for(int k=0;k<=t;k++)
{
dp[u][k]+=a[u];
}
}
int main()
{
while(scanf("%d%d",&n,&t)!=EOF)
{
int i,j,u,v,w;
NE=ans=0;
memset(dp,0,sizeof(dp));
memset(head,-1,sizeof(head));
for(i=1; i<n; i++)
{
scanf("%d%d%d",&u,&v,&w);
addEdge(u,v,w);
addEdge(v,u,w);
}
for(i=1;i<=n;i++)
{
cin>>a[i];
}
dfs1(1,0);
if(ans>t)
{
puts("Human beings die in pursuit of wealth, and birds die in pursuit of food!");
continue;
}
t-=ans;
dfs2(1,0);
printf("%d\n",dp[1][t]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: