题意:给一棵有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;
}