zoukankan      html  css  js  c++  java
  • POJ 2152 Fire(树形dp)

    http://poj.org/problem?id=2152

    题意:

    n个节点组成的树,要在树一些点上建立消防站,每个点建站都有个cost[i],每个点如果不在当前的点上建站,也要依赖其他的消防站,并且距离不超过limit[i]。求符合上述条件的最小费用建站费用。

    思路:

    感觉有点无从下手,如果不会的话可以先看一下一张一弛,解题之道这篇论文。

    其实说白了,就是暴力枚举。

    先设立一个辅助数组$best$,$best[u]$表示以u及其子树的最小费用,$dp[u][j]$表示u依赖j节点时(也就是j节点建消防站)及其子节点的最小费用。(如果u和j之间的距离>$limit[u]$则不需要考虑)

    那么状态转移方程就是:$dp[u][j]+=min(dp[v][j]-cost[j],best[v])$,$dp[v][j]-cost[j]$表示v也依赖j节点时的最小费用,因为前面已经计算过了$cost[j]$,所以这里需要减去。

    在每次考虑了u可以依赖的节点j后,更新一下最小值$best[u]$即可。最后的答案即是$best[1]$。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<vector>
     6 #include<stack>
     7 #include<queue>
     8 #include<cmath>
     9 #include<map>
    10 #include<set>
    11 using namespace std;
    12 typedef long long ll;
    13 typedef pair<int,int> pll;
    14 const int INF = 0x3f3f3f3f;
    15 const int maxn=1000+5;
    16 
    17 int n,root;
    18 int cost[maxn],limit[maxn],best[maxn],dp[maxn][maxn],dis[maxn][maxn];
    19 vector<pll> G[maxn];
    20 
    21 void calc_dis(int u, int fa, int d)
    22 {
    23     dis[root][u]=d;
    24     for(int i=0;i<G[u].size();i++)
    25     {
    26         int v=G[u][i].first;
    27         int w=G[u][i].second;
    28         if(v==fa)  continue;
    29         calc_dis(v,u,d+w);
    30     }
    31 }
    32 
    33 void dfs(int u, int fa)
    34 {
    35     for(int i=0;i<G[u].size();i++)
    36     {
    37         int v=G[u][i].first;
    38         if(v==fa)  continue;
    39         dfs(v,u);
    40     }
    41     for(int j=1;j<=n;j++)
    42     {
    43         if(dis[u][j]>limit[u])  continue;
    44         dp[u][j]=cost[j];
    45         for(int i=0;i<G[u].size();i++)
    46         {
    47             int v=G[u][i].first;
    48             int w=G[u][i].second;
    49             if(v==fa)  continue;
    50             dp[u][j]+=min(dp[v][j]-cost[j],best[v]);
    51         }
    52         best[u]=min(best[u],dp[u][j]);
    53     }
    54 }
    55 
    56 int main()
    57 {
    58    //freopen("in.txt","r",stdin);
    59     int T;
    60     int kase=0;
    61     scanf("%d",&T);
    62     while(T--)
    63     {
    64         scanf("%d",&n);
    65         for(int i=1;i<=n;i++)  {G[i].clear();scanf("%d",&cost[i]);}
    66         for(int i=1;i<=n;i++)   scanf("%d",&limit[i]);
    67         for(int i=1;i<n;i++)
    68         {
    69             int u,v,w;
    70             scanf("%d%d%d",&u,&v,&w);
    71             G[u].push_back(make_pair(v,w));
    72             G[v].push_back(make_pair(u,w));
    73         }
    74         for(int i=1;i<=n;i++)  {root=i;calc_dis(i,-1,0);}
    75         memset(dp,0x3f,sizeof(dp));
    76         memset(best,0x3f,sizeof(best));
    77         dfs(1,-1);
    78         printf("%d
    ",best[1]);
    79     }
    80     return 0;
    81 }
  • 相关阅读:
    多线程
    IO
    Collections工具类
    File类
    Map
    List与Set接口
    如何把数学作为一种工具
    包装类
    异常
    内部类
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7442852.html
Copyright © 2011-2022 走看看