您的位置:首页 > 其它

hdu 4276 树形dp

2015-05-12 17:37 246 查看
题意:给你n个点,n-1条边构成树,每条边有边权(表示走每条边的时间),每个点有点权,问在时间T从点1走到点n,能够得到最多的点权有多少。

由于是树,最优的结果一定经过最短路,其他边要么经过两次,要么零次,所以先求最短路,权置为零,之后dp,最短路直接搜索即可(树)

其他路一定是经过然后再返回到最短路径上

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
#define MOD 1000000007
const int INF=1000010;
const double eps=1e-5;
typedef long long ll;
#define cl(a) memset(a,0,sizeof(a))
#define ts printf("*****\n");
const int MAXN=1005;
int n,m,tt,tot=0,head[MAXN],dp[MAXN][MAXN],val[MAXN];
int maxw,mint;
struct edge
{
int to,next;
int w;
}edge[MAXN*2];
void addedge(int a,int b,int w)
{
edge[tot].to=a;
edge[tot].next=head[b];
edge[tot].w=w;
head[b]=tot++;
}
void init()
{
memset(head,-1,sizeof(head));
tot=0;
cl(dp);
}
bool dfs1(int u,int pre)
{
if(u==n)    return 1;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(v==pre)  continue;
if(dfs1(v,u))
{
mint+=edge[i].w;
edge[i].w=0;
return 1;
}
}
return 0;
}
void dfs2(int u,int pre)
{
for(int i=0;i<=m;i++)   dp[u][i]=val[u];
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(v==pre)  continue;
dfs2(v,u);
int minc=edge[i].w*2;
for(int j=m;j>=minc;j--)
{
for(int k=0;j-k>=minc;k++)
{
dp[u][j]=max(dp[u][j],dp[v][k]+dp[u][j-k-minc]);
}
}
}
}
int main()
{
int i,j,k;
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
if(n==0&&m==0)  break;
int u,v,w;
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++)
scanf("%d",val+i);
mint=0;
dfs1(1,-1);
if(mint>m)
{
printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n");
continue;
}
m-=mint;
dfs2(1,-1);
printf("%d\n",dp[1][m]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: