题意:给出一棵n个节点的树,起点1,终点n,相连的两个节点之间有距离,每个节点有个价值,给出一个时间T。问从1到达n在给定时间T内取得的最大价值?
思路:先从1走到n,如果总的时间不够走完,直接退出,否则把时间扣掉,这些边权设置为0,然后做一遍树形DP
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 int n,m; 7 int tot,go[200005],first[200005],next[200005],val[200005]; 8 int c[200005],vis[200005],pre[200005],edge[200005],op[200005]; 9 int f[505][505],v[200005]; 10 int read(){ 11 int t=0,f=1;char ch=getchar(); 12 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 13 while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} 14 return t*f; 15 } 16 void insert(int x,int y,int z){ 17 tot++; 18 go[tot]=y; 19 next[tot]=first[x]; 20 first[x]=tot; 21 val[tot]=z; 22 } 23 void add(int x,int y,int z){ 24 insert(x,y,z);op[tot]=tot+1; 25 insert(y,x,z);op[tot]=tot-1; 26 } 27 void bfs(){ 28 for (int i=1;i<=n;i++) vis[i]=pre[i]=edge[i]=0; 29 int h=0,t=1; 30 c[1]=1;vis[1]=1; 31 while (h<=t){ 32 h++; 33 for (int i=first[c[h]];i;i=next[i]){ 34 int pur=go[i]; 35 if (vis[pur]) continue; 36 pre[pur]=c[h]; 37 edge[pur]=i; 38 c[++t]=pur; 39 vis[pur]=1; 40 } 41 } 42 } 43 void prework(){ 44 for (int i=n;i!=1;i=pre[i]){ 45 m-=val[edge[i]]; 46 val[edge[i]]=val[op[edge[i]]]=0; 47 } 48 } 49 void dfs(int x,int fa){ 50 for (int i=0;i<=m;i++) f[x][i]=0; 51 for (int i=first[x];i;i=next[i]){ 52 int pur=go[i]; 53 if (pur==fa) continue; 54 dfs(pur,x); 55 int dis=val[i]; 56 dis*=2; 57 for (int k=m;k>=dis;k--) 58 for (int j=0;j+dis<=k;j++) 59 f[x][k]=std::max(f[x][k],f[pur][j]+f[x][k-j-dis]); 60 } 61 for (int i=0;i<=m;i++) 62 f[x][i]+=v[x]; 63 } 64 int main(){ 65 while (scanf("%d%d",&n,&m)!=EOF){ 66 if (n==0&&m==0) return 0; 67 tot=0; 68 for (int i=1;i<=n;i++) first[i]=0; 69 for (int i=1;i<n;i++){ 70 int x,y,z; 71 x=read();y=read();z=read(); 72 add(x,y,z); 73 } 74 for (int i=1;i<=n;i++) v[i]=read(); 75 bfs(); 76 prework(); 77 if (m<0){ 78 printf("Human beings die in pursuit of wealth, and birds die in pursuit of food! "); 79 continue; 80 } 81 dfs(1,0); 82 printf("%d ",f[1][m]); 83 } 84 return 0; 85 }