题意:
给你一颗树,然后每个点有一个价值,每个边有一个代价,然后问你,从k点出发,花费最多m/2的代价,能够取得最多的价值是多少。
思路:
树上背包问题,dp[i][j]表示从i点出发,花费j的代价所能取得的最大价值是多少。
转移方程为 dp[i][j]=max(dp[i][j],dp[i][m-k-t[i][v]]+dp[v][k]) 就是以u为父节点 走不走v这个点 从不同的费用转移过来
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 5e4+10;
int n,val[105],k,m;
int dp[105][205],vis[105];
vector<pair<int,int> > G[105];
void dfs(int u){
vis[u] = 1;
dp[u][0] = val[u];
for(int i=0; i<G[u].size(); i++){
int v = G[u][i].first, w = G[u][i].second;
if(vis[v]==0){
dfs(v);
for(int j=m; j>=0; j--)
for(int k=0; k<=j-w; k++)
dp[u][j] = max(dp[u][j],dp[u][j-k-w]+dp[v][k]);
}
}
}
int main(){
while(cin >> n){
memset(dp,0,sizeof(dp));
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
G[i].clear();
for(int i=1; i<=n; i++){
cin >> val[i];
dp[i][0] = val[i];
}
for(int i=1; i<=n-1; i++){
int a,b,c; cin>>a>>b>>c;
G[a].push_back(make_pair(b,c));
G[b].push_back(make_pair(a,c));
}
cin >> k >> m;
m = m/2;
dfs(k);
int ans = 0;
for(int i=0; i<=m; i++)
if(dp[k][i] > ans)
ans = max(ans,dp[k][i]);
cout << ans << endl;
}
}