很久很久以前有一个吸血鬼,每m天就会出现一次,把不在自己村子呆着的冒险家吃掉。有n个村子,n-1条道路,每个村子都有一定数量的财富,默认探险家刚一到达一个村子就能获得财富,给出探险家的出生的村子和多少天后吸血鬼出现。
要求在吸血鬼出现之前赶回自己的村子,其实就是求一棵以k为根的各点权值之和最大且各边权加起来<=m/2的子树。
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <queue> #include <ctime> #include <vector> #include <algorithm> #define LL __int64 #define inf 1<<29 using namespace std; struct Edge { int v,next; int len; }edge[1000]; int num; int head[1000]; void addedge(int u,int v,int len) { edge[num].v=v; edge[num].len=len; edge[num].next=head[u]; head[u]=num++; edge[num].v=u; edge[num].len=len; edge[num].next=head[v]; head[v]=num++; } int a[222]; int dp[222][222]; int n,m,k; void dfs(int root,int father,int d) { for(int i=head[root];i!=-1;i=edge[i].next) { int v=edge[i].v; int len=edge[i].len; if(v==father) { continue; } dfs(v,root,d-len); for(int j=d;j>=0;j--) { for(int k=0;k+len<=j;k++) { if(dp[v][k]!=0&&dp[root][j-k-len]!=0) { dp[root][j]=max(dp[root][j],dp[root][j-k-len]+dp[v][k]); } } } } } int main() { int u,v,len; while(scanf("%d",&n)!=EOF) { memset(dp,0,sizeof(dp)); memset(head,-1,sizeof(head)); num=0; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); dp[i][0]=a[i]; } for(int i=1;i<n;i++) { scanf("%d%d%d",&u,&v,&len); addedge(u,v,len); } scanf("%d%d",&k,&m); m/=2; dp[k][0]=a[k]; dfs(k,-1,m); int ans=-1; for(int i=0;i<=m;i++) { if(dp[k][i]>ans) { ans=dp[k][i]; } } printf("%d\n",ans); } return 0; }
时间: 2024-11-05 14:54:36