ZOJ 3626 Treasure Hunt I(树型DP+01背包)

题意:给一棵有n个结点的树,每个点有点权表示在这个点上的价值,每条边有边权表示走这条路所需要的时候,给一个时间m,问在时间m从点k出发再回到点k所能得到的最大的价值和。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=105;
int n,m,k;
int data[N],head[N],tot;
int dp[N][205];
struct Edge
{
	int to,valu,pre;
	Edge(){}
	Edge(int a,int b,int c){to=a;valu=b;pre=c;}
}edge[N];
void addEdge(int a,int b,int c)
{
	edge[tot]=Edge(b,c,head[a]);
	head[a]=tot++;
}
void dfs(int u,int fa,int day)
{
	for(int i=head[u];i!=-1;i=edge[i].pre)
	{
		int v=edge[i].to,valu=edge[i].valu;
		if(v==fa) continue;
		dfs(v,u,day-edge[i].valu);
		for(int j=day;j>=0;j--)
		{
			for(int k=0;k+valu<=j;k++)
			{
				if(dp[v][k]!=-1&&dp[u][j-k-valu]!=-1)
				{
					dp[u][j]=max(dp[u][j],dp[u][j-k-valu]+dp[v][k]);
				}
			}
		}
	}
}
int main()
{
	while(scanf("%d",&n)!=EOF)
	{
		tot=0;
		memset(head,-1,sizeof(head));
		memset(dp,-1,sizeof(dp));

		for(int i=1;i<=n;i++)
		{
			scanf("%d",&data[i]);
			dp[i][0]=data[i];
		}
		for(int i=0;i<n-1;i++)
		{
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			addEdge(a,b,c);
			addEdge(b,a,c);
		}
		scanf("%d%d",&k,&m);
		m/=2;
		dfs(k,-1,m);

		int res=0;
		for(int i=0;i<=m;i++) res=max(res,dp[k][i]);
		printf("%d\n",res);
	}
	return 0;
}



你可能感兴趣的:(c,struct)