POJ 2152 Fire

Fire

Time Limit: 2000ms
Memory Limit: 65536KB
This problem will be judged on PKU. Original ID: 2152
64-bit integer IO format: %lld      Java class name: Main
 
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

 
解题:楼教主的题目真的很难
 
参考这位大牛的博客
 
$dp[i][j]表示结点i靠j消防,best[i]表示以i为根的子树的每个节点以u内的某个节点作为负责站的最小花费$
 
$$best[u] = min(dp[u][i])  i in subtree(u)$$
 
$if dis(u,i) > d_u ,u 不能靠i来消防$
$if dis(u,i) leq d_u,这时候u可以靠i来消防,u的儿子也可以靠i来消防,儿子也可以靠自己内部的点来消防$
$初始化条件 dp[u][i]  = dis(u,i) leq limit[u]?cost[u]:+infty$
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 const int maxn = 1010;
 6 const int INF = 0x3f3f3f3f;
 7 struct arc{
 8     int to,w,next;
 9     arc(int x = 0,int y = 0,int z = -1){
10         to = x;
11         w = y;
12         next = z;
13     }
14 }e[maxn*2];
15 int head[maxn],w[maxn],d[maxn],best[maxn],dis[maxn][maxn],tot,n;
16 int dp[maxn][maxn],m;
17 void add(int u,int v,int w){
18     e[tot] = arc(v,w,head[u]);
19     head[u] = tot++;
20 }
21 void dfs(int u,int fa,int dd,int root){
22     dis[root][u] = dd;
23     for(int i = head[u]; ~i; i = e[i].next){
24         if(e[i].to == fa) continue;
25         dfs(e[i].to,u,dd + e[i].w,root);
26     }
27 }
28 void solve(int u,int fa){
29     for(int i = 1; i <= n; ++i)
30         if(dis[u][i] <= d[u]) dp[u][i] = w[i];
31     for(int i = head[u]; ~i; i = e[i].next){
32         if(e[i].to == fa) continue;
33         solve(e[i].to,u);
34         for(int j = 1; j <= n; ++j)
35             if(dis[u][j] <= d[u]) 
36                 dp[u][j] += min(dp[e[i].to][j] - w[j],best[e[i].to]);
37     }
38     for(int i = 1; i <= n; ++i) best[u] = min(best[u],dp[u][i]);
39 }
40 int main(){
41     int kase,u,v,ww;
42     scanf("%d",&kase);
43     while(kase--){
44         memset(head,-1,sizeof head);
45         scanf("%d",&n);
46         for(int i = 1; i <= n; ++i)
47             scanf("%d",w + i);
48         for(int i = 1; i <= n; ++i)
49             scanf("%d",d + i);
50         tot = 0;
51         for(int i = 1; i < n; ++i){
52             scanf("%d%d%d",&u,&v,&ww);
53             add(u,v,ww);
54             add(v,u,ww);
55         }
56         memset(dp,0x3f,sizeof dp);
57         memset(best,0x3f,sizeof best);
58         for(int i = 1; i <= n; ++i) dfs(i,-1,0,i);
59         solve(1,-1);
60         printf("%d
",best[1]);
61     }
62     return 0;
63 }
View Code
原文地址:https://www.cnblogs.com/crackpotisback/p/4789796.html