POJ - 2152 Fire 树型DP

题目大意:有N座城市,要求在这N座城市中建一个消防系统,使得每座城市城市着火时都能被按时扑灭

现在给出每座城市建一个消防站所需的花费w和每座城市相邻消防站的最远距离lim(和该城市距离超过lim的城市的消防站无法救该城市的火),问要使所有的城市都能被救到火,建消防站的最小花费是多少

解题思路:参考了别人的题解,果然还是太弱了。。。

要使该城市能被救到火,那么消防站不是建在该点,就是建在以该点为根的子树上,或者是该点的父节点上,他肯定要依赖其中一个城市的消防站的

设dp[i][j]表示以i城市为根的树依赖j城市消防站的最低花费(该树的每个节点都符合要求),best[i]为以i城市为根的树最低消费(该树的所有节点都符合要求)

那么状态转移方程就是

dp[i][j] = w[j] + sum (min(dp[k][j] - w[j], best[k])) (k为i的子节点)

dp[k][j]表示因为k可以和i节点一样依赖于j,那么花费就是dp[k][j] - w[j],或者k节点不依赖于j,而依赖于别的节点,那就是best[k]了

以上参考了:http://blog.csdn.net/woshi250hua/article/details/7725917

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
#define maxn 1010
#define INF 0x3f3f3f3f
struct Node{
    int v, l;
    Node() {}
    Node(int vv, int ll) {
        v = vv;
        l = ll;
    }
};
vector<Node> node[maxn];
int dp[maxn][maxn], dis[maxn][maxn], w[maxn], lim[maxn], best[maxn];
int n, now;

void dfs(int cur, int f, int d) {
    dis[now][cur] = d;
    int u;
    for(int i = 0; i < node[cur].size(); i++) {
        if( ( u = node[cur][i].v) != f)
            dfs(u,cur,d + node[cur][i].l);
    }
}

void init() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        node[i].clear();
        best[i] = INF;
    }

    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            dp[i][j] = INF;
    for(int i = 1; i <= n; i++)
        scanf("%d", &w[i]);
    for(int i = 1; i <= n; i++)
        scanf("%d", &lim[i]);
    int x, y, z;
    for(int i = 0; i < n - 1; i++) {
        scanf("%d%d%d", &x, &y, &z);
        node[x].push_back(Node(y,z));
        node[y].push_back(Node(x,z));
    }

    for(int i = 1; i <= n; i++) {
        now = i;
        dfs(i,0,0);
    }
}

void DP(int cur, int f) {
    int u;
    for(int i = 0; i < node[cur].size(); i++)
        if((u = node[cur][i].v) != f)
            DP(u, cur);

    for(int i = 1; i <= n; i++) {
        if(dis[cur][i] <= lim[cur])
            dp[cur][i] = w[i];
        for(int j = 0; j < node[cur].size(); j++) {
            if((u = node[cur][j].v) != f) {
                dp[cur][i] += min(dp[u][i] - w[i], best[u]);
            }
        }
        best[cur] = min(dp[cur][i], best[cur]);
    }
}

int main() {
    int test;
    scanf("%d", &test);
    while(test--) {
        init();
        DP(1,0);
        printf("%d\n", best[1]);
    }
    return 0;
}
时间: 2024-10-09 11:47:19

POJ - 2152 Fire 树型DP的相关文章

POJ 2152 Fire (树形DP,经典)

题意:给定一棵n个节点的树,要在某些点上建设消防站,使得所有点都能够通过某个消防站解决消防问题,但是每个点的建站费用不同,能够保证该点安全的消防站的距离上限也不同.给定每个点的建站费用以及最远的消防站距离上限,求保证该树安全的最小花费. 思路: 要选择部分点来建站解决消防问题,而总花费是有最优解的. 如何进行树形DP? 假设某点t的所有子树的消防问题都解决,而且已经获得最优解了,那么现在考虑的是点t的最优解问题,点t可以依靠任何点只要不超过距离限制即可,那枚举一下所有点试试,一旦t依靠某个点j解

【POJ 2486】 Apple Tree(树型dp)

[POJ 2486] Apple Tree(树型dp) Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8981   Accepted: 2990 Description Wshxzt is a lovely girl. She likes apple very much. One day HX takes her to an apple tree. There are N nodes in the tree. Each

HDU_1520_Anniversary party_树型dp

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1520 Anniversary party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 8233    Accepted Submission(s): 3574 Problem Description There is going to b

HDU1561 The more, The Better(树型DP)

题目是有n个存有宝藏的城堡,攻克任何一个城堡都需要先攻克0个或其他1个城堡,问攻克m个城堡最多能得到多少宝藏. 题目给的城堡形成一个森林,添加一个超级根把森林连在一起就是树了,那么就考虑用树型DP: dp[u][m]表示以u结点为根的子树攻克m个结点的最大价值 但是这样转移太难了,根是从每个孩子通过各自分配若干的城堡去攻克转移的,一个排列组合数,阶乘,是指数级的时间复杂度! 看了题解,原来这是依赖背包,没看背包九讲..不过网上的博客似乎没说清楚,事实上这个状态应该是三个维度来表示: dp[u][

POJ3659 Cell Phone Network(树上最小支配集:树型DP)

题目求一棵树的最小支配数. 支配集,即把图的点分成两个集合,所有非支配集内的点都和支配集内的某一点相邻. 听说即使是二分图,最小支配集的求解也是还没多项式算法的.而树上求最小支配集树型DP就OK了. 树上的每个结点作为其子树的根可以有三个状态: 不属于支配集且还没被支配 不属于支配集但被其孩子支配 属于支配集 那么就是用dp[u][1\2\3]来表示动归的状态. 123转移该怎么转移就怎么转移..最后的结果就是min(dp[root][2],dp[root][3]). 要注意的是对于有些结点前2

HDU_1561_The more, The Better_树型dp

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1561 The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 7031    Accepted Submission(s): 4121 Problem Description ACboy很喜欢玩一种战略游戏,

二叉苹果树(树型DP+背包)

二叉苹果树 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点).这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置.下面是一颗有4个树枝的树: 2   5 \  / 3  4 \  / 1 现在这颗树枝条太多了,需要剪枝.但是一些树枝上长有苹果. 给定需要保留的树枝数量,求出最多能留住多少苹果. 程序名:apple 输入格式: 第1行2个数,N和Q(1<=Q<= N,1<N<=

HDU_1011_Starship Troopers_树型dp

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1011 Starship Troopers Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 16276    Accepted Submission(s): 4335 Problem Description You, the leader o

【HDOJ 5834】Magic boy Bi Luo with his excited tree(树型DP)

[HDOJ 5834]Magic boy Bi Luo with his excited tree(树型DP) Magic boy Bi Luo with his excited tree Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description Bi Luo is a magic boy, he also has a migic tree,