hdu 3586 Information Disturbing(树形dp)

Information Disturbing

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3586

解题思路:

题目大意:

给你n个敌方据点,1为司令部,其他点各有一条边相连构成一棵树,每条边都有一个权值val表示破坏这条边的费用,叶子节点为前

线。现要切断前线和司令部的联系,每次切断边的费用不能超过上限limit,问切断所有前线与司令部联系所花费的总费用少于m时的

最小limit。

算法思想:

容易看出这题要用树形DP不难,但是难在想到要二分。对于上限进行二分,然后通过树形DP进行判断。

坑点:INF设置不能太大。。。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#define INF 1000005;
using namespace std;

const int N = 1005;
struct node{
    int v,val;
    node(){}
    node(int _v,int _val){
        v = _v; val = _val;
    }
};
vector<node> edge[N];
int n,m;
int dp[N];

void dfs(int u,int fa,int lim){
    int flag = 0; //标记是不是叶子结点
    dp[u] = 0;
    int len = edge[u].size();
    for(int i = 0; i < len; ++i){
        int v = edge[u][i].v;
        if(v != fa){
            flag = 1;
            dfs(v,u,lim);
            if(edge[u][i].val <= lim)
                dp[u] += min(dp[v],edge[u][i].val);
            else
                dp[u] += dp[v];
        }
    }
    if(!flag)   //叶子结点无穷大
        dp[u] = INF;
}

int main(){
    while(scanf("%d%d",&n,&m),n+m){
        for(int i = 0; i <= n; ++i)
            edge[i].clear();
        int MAX = 0;
        int u,v,val;
        for(int i = 1; i < n; ++i){
            scanf("%d%d%d",&u,&v,&val);
            edge[u].push_back(node(v,val));
            edge[v].push_back(node(u,val));
            if(val > MAX)
                MAX = val;
        }
        int l = 1,r = MAX,ans = -1;
        while(l <= r){
            int mid = (l+r)>>1;
            dfs(1,-1,mid);
            if(dp[1] <= m){
                ans = mid;
                r = mid-1;
            }else
                l = mid+1;
        }
        printf("%d\n",ans);
    }
    return 0;
}


你可能感兴趣的:(hdu 3586 Information Disturbing(树形dp))