题意:这一题是陈启锋的论文中的一道题 题意是在一棵树上选取节点建立消防站 每个节点有一个代价 然后每个节点之间又有距离 距离大于每个节点承受上限的化就不能被看管 然后问题的看管所有节点最小代价是多少
解法:正确的姿势就是利用dfs进行dp 枚举每一个节点被看管的节点 然后得到的dp方式是当前节点被i节点看管的最少花费取决于每一颗 子树分别被全部看管的最佳花费或者是儿子节点也同样被i看管带来的花费
#include<cstdio>
#include<vector>
#include<limits.h>
using namespace std;
#define maxn 1111
#define INF 2147483647
#define min(a,b) (a)<(b)?(a):(b)
#define max(a,b) (a)>(b)?(a):(b)
struct edge{int v,w;}s;
vector<edge>e[maxn];
int n,cur,best[maxn],dp[maxn][maxn],dist[maxn][maxn],limit[maxn],cost[maxn];
void init(){
for(int i=0;i<=n;++i)e[i].clear(),best[i]=INT_MAX;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
dp[i][j]=INT_MAX;
}
void Dis(int u,int f,int dis){
dist[cur][u]=dis;
for(int i=0;i<e[u].size();++i){
int v=e[u][i].v;
int len=e[u][i].w;
if(v==f)continue;
Dis(v,u,dis+len);
}
}
void solve(int u,int f){
for(int i=0;i<e[u].size();++i){
if(e[u][i].v!=f)solve(e[u][i].v,u);
}
for(int i=1;i<=n;++i)
if(dist[u][i]<=limit[u]){
dp[u][i]=cost[i];
for(int j=0;j<e[u].size();++j){
int v=e[u][j].v;
if(v==f)continue;
dp[u][i]+=min(dp[v][i]-cost[i],best[v]);
}
best[u]=min(best[u],dp[u][i]);
}
}
int _,a,b,c;
int main(){
scanf("%d",&_);
while(_--){
scanf("%d",&n);
init();
for(int i=1;i<=n;++i)scanf("%d",&cost[i]);
for(int i=1;i<=n;++i)scanf("%d",&limit[i]);
for(int i=1;i<n;++i){
scanf("%d%d%d",&a,&b,&c);
s.v=b,s.w=c;
e[a].push_back(s);
s.v=a,s.w=c;
e[b].push_back(s);
}
for(int i=1;i<=n;++i)
cur=i,Dis(i,0,0);
solve(1,0);
printf("%d\n",best[1]);
}
return 0;
}