POJ 2152 Fire(树形DP)

题意:

思路:令F[i][j]表示

的最小费用。Best[i]表示以i为根节点的子树多有节点都找到负责消防站的最小费用。

好难的题。。。

 1 #include<algorithm>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iostream>
 6 int tot,go[200005],first[200005],next[200005],val[200005];
 7 int dis[200005],f[2005][2005];
 8 int n,w[200005],d[200005],best[200005];
 9 void insert(int x,int y,int z){
10     tot++;
11     go[tot]=y;
12     next[tot]=first[x];
13     first[x]=tot;
14     val[tot]=z;
15 }
16 void add(int x,int y,int z){
17     insert(x,y,z);
18     insert(y,x,z);
19 }
20 void Dfs(int x){
21     for (int i=first[x];i;i=next[i]){
22         int pur=go[i];
23         if (dis[pur]!=-1) continue;
24         dis[pur]=dis[x]+val[i];
25         Dfs(pur);
26     }
27 }
28 void dfs(int x,int fa){
29     for (int i=first[x];i;i=next[i]){
30         int pur=go[i];
31         if (pur==fa) continue;
32         dfs(pur,x);
33     }
34     for (int i=1;i<=n;i++) dis[i]=-1;
35     dis[x]=0;
36     Dfs(x);best[x]=99999999;
37     for (int i=1;i<=n;i++) f[x][i]=99999999;
38     for (int i=1;i<=n;i++)
39      if (dis[i]<=d[x]){
40             f[x][i]=w[i];
41             for (int j=first[x];j;j=next[j]){
42                 int pur=go[j];
43                 if (pur==fa) continue;
44                 f[x][i]+=std::min(best[pur],f[pur][i]-w[i]);
45             }
46             best[x]=std::min(best[x],f[x][i]);
47     }
48 }
49 int main(){
50     int T;
51     scanf("%d",&T);
52     while (T--){
53         scanf("%d",&n);
54         for (int i=1;i<=n;i++) scanf("%d",&w[i]);
55         for (int i=1;i<=n;i++) scanf("%d",&d[i]);
56         tot=0;
57         for (int i=1;i<=n;i++) first[i]=0;
58         for (int i=1;i<n;i++){
59             int x,y,z;
60             scanf("%d%d%d",&x,&y,&z);
61             add(x,y,z);
62         }
63         dfs(1,0);
64         printf("%d
",best[1]);
65     }
66 }
原文地址:https://www.cnblogs.com/qzqzgfy/p/5553912.html