POJ 2152 Fire

Description

Country Z has N cities, which are numbered from 1 to N. Cities are connected by highways, and there is exact one path between two different cities. Recently country Z often caught fire, so the government decided to build some firehouses in some cities. Build a firehouse in city K cost W(K). W for different cities may be different. If there is not firehouse in city K, the distance between it and the nearest city which has a firehouse, can’t be more than D(K). D for different cities also may be different. To save money, the government wants you to calculate the minimum cost to build firehouses.

Input

The first line of input contains a single integer T representing the number of test cases. The following T blocks each represents a test case.

The first line of each block contains an integer N (1 < N <= 1000). The second line contains N numbers separated by one or more blanks. The I-th number means W(I) (0 < W(I) <= 10000). The third line contains N numbers separated by one or more blanks. The I-th number means D(I) (0 <= D(I) <= 10000). The following N-1 lines each contains three integers u, v, L (1 <= u, v <= N,0 < L <= 1000), which means there is a highway between city u and v of length L.

Output

For each test case output the minimum cost on a single line.

Sample Input

5
5
1 1 1 1 1
1 1 1 1 1
1 2 1
2 3 1
3 4 1
4 5 1
5
1 1 1 1 1
2 1 1 1 2
1 2 1
2 3 1
3 4 1
4 5 1
5
1 1 3 1 1
2 1 1 1 2
1 2 1
2 3 1
3 4 1
4 5 1
4
2 1 1 1
3 4 3 2
1 2 3
1 3 3
1 4 2
4
4 1 1 1
3 4 3 2
1 2 3
1 3 3
1 4 2

Sample Output

2
1
2
2
3

Source

POJ Monthly,Lou Tiancheng


lyd课件上的题,(((φ(◎ロ◎;)φ)))看不懂啊。一看是楼教出的题,也就。。

查题解时发现是陈启峰论文里的,写得很不错。附链接——https://wenku.baidu.com/view/82124f74f242336c1eb95e44.html

dp[i][j]表示以i为根的子树里修建一些消防站,并在节点j处修建一消防站,i的负责站必须是j;

best[i]:表示表示以i为根的子树的所有节点都有负责站的最小花费。

 dist[i]:表示i到x的距离(每换换一个节点,都要再求一次dist[])。

状态状态转移方程:dp[i][j]=w[j]+sum(min(best[y],dp[y][j]-w[i]))(y是i的所有孩子);


#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=1005;
int T,n,cnt,w[N],d[N],dp[N][N],f[N],dis[N],hd[N];
struct node
{
	int to,nxt,l;
}v[2*N];
void addedge(int x,int y,int z)
{
	++cnt;
	v[cnt].to=y;
	v[cnt].l=z;
	v[cnt].nxt=hd[x];
	hd[x]=cnt;
}
void dist(int u)
{
	for(int i=hd[u];i;i=v[i].nxt)
		if(dis[v[i].to]==-1)
		{
			dis[v[i].to]=dis[u]+v[i].l;
			dist(v[i].to);
		}
}
void dfs(int u,int fa)
{
	for(int i=hd[u];i;i=v[i].nxt)
		if(v[i].to!=fa)
			dfs(v[i].to,u);
	memset(dis,-1,sizeof(dis));
	dis[u]=0;
	f[u]=1e9+7;
	dist(u);
	for(int i=1;i<=n;i++)
	{
		if(dis[i]>d[u])
			dp[u][i]=1e9+7;
		else
		{
			dp[u][i]=w[i];
			for(int j=hd[u];j;j=v[j].nxt)
				if(v[j].to!=fa)
					dp[u][i]+=min(f[v[j].to],dp[v[j].to][i]-w[i]);
			f[u]=min(f[u],dp[u][i]);
		}
	}
}
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		cnt=0;
		memset(hd,0,sizeof(hd));
		memset(f,0x3f,sizeof(f));
		memset(dp,0x3f,sizeof(dp));
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
			scanf("%d",&w[i]);
		for(int i=1;i<=n;i++)
			scanf("%d",&d[i]);
		for(int i=1;i<=n-1;i++)
		{
			int x,y,z;
			scanf("%d%d%d",&x,&y,&z);
			addedge(x,y,z);
			addedge(y,x,z);
		}
		dfs(1,0);
		printf("%d\n",f[1]);
	}
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值