题目链接:http://poj.org/problem?id=2152
题目大意:在一棵树形的城市中建立一些消防站,但每个城市有一个最大距离限制,求需要的最小花费。
题目思路:树形dp,定义dp[i][j]为以i为根的子树且i的消防站建在j的最小花费,best[i]为以i为根的子树的最小花费,则dp[i][j]=w[j]+sum(min(dp[child][j]-w[j],best[child]));
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<queue>
#include<algorithm>
#include<vector>
#include<stack>
#include<list>
#include<iostream>
#include<map>
using namespace std;
#define inf 0x3f3f3f3f
#define Max 110
int max(int a,int b)
{
return a>b?a:b;
}
inline int min(int a,int b)
{
return a<b?a:b;
}
int t,n;
int dp[1010][1010],best[1010],w[1010],d[1010],D[1010],p[1010],eid;
struct node
{
int to,next,len;
}e[2*1010];
inline void addedge(int u,int v,int len)
{
e[eid].to=v;
e[eid].len=len;
e[eid].next=p[u];
p[u]=eid++;
}
void dis(int u)
{
int i;
for(i=p[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(d[v]==-1)
{
d[v]=d[u]+e[i].len;
dis(v);
}
}
}
void dfs(int u,int pre)
{
int i,j;
for(i=p[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(v!=pre)
dfs(v,u);
}
for(i=1;i<=n;i++)
d[i]=-1;
d[u]=0;
dis(u);
// for(i=1;i<=n;i++)
// printf("u %d i %d dis %d\n",u,i,d[i]);
for(i=1;i<=n;i++)
{
dp[u][i]=inf;
if(d[i]>D[u])
continue;
dp[u][i]=w[i];
for(j=p[u];j!=-1;j=e[j].next)
{
int v=e[j].to;
if(v!=pre)
dp[u][i]+=min(best[v],dp[v][i]-w[i]);
}
// printf("u %d i %d dp %d\n",u,i,dp[u][i]);
best[u]=min(best[u],dp[u][i]);
}
}
int main()
{
int i,j,k,u,v,len;
scanf("%d",&t);
while(t--)
{
eid=0;
memset(p,-1,sizeof(p));
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&w[i]);
for(i=1;i<=n;i++)
scanf("%d",&D[i]);
for(i=1;i<n;i++)
{
scanf("%d%d%d",&u,&v,&len);
addedge(u,v,len);
addedge(v,u,len);
}
for(i=1;i<=n;i++)
best[i]=inf;
dfs(1,0);
printf("%d\n",best[1]);
}
}