HDU 3586 Information Disturbing (树形DP+二分)

来源:互联网 发布:怎样使用淘宝金币 编辑:程序博客网 时间:2024/05/06 07:16

思路:二分上限,求出删去一些满足条件的边后使根节点和所有叶节点不相连的最小花费。

设dp[i]为在i为根节点的子树中使i节点与叶节点分离的最小花费。

父节点为u,子节点为v,边权为cost。

初值:叶节点值为INF。

如果cost<= limit ,dp[u] += min(cost,dp[v])

反之,dp[u] += dp[v]。


代码:

#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>using namespace std;const int maxn = 1005;const int INF = 1e6+5;struct Nod{    int b,val,next;    void init(int b,int val,int next){        this->b=b;this->val=val;this->next=next;    }}buf[maxn<<1];int len,E[maxn];int n,m;int dp[maxn];void init(){    len=0;    memset(E,-1,sizeof(E));    //(dp,0,sizeof(dp));}void add_edge(int a,int b,int val){    buf[len].init(b,val,E[a]);E[a]=len++;    buf[len].init(a,val,E[b]);E[b]=len++;}void dfs(int u,int pre,int lim){    int i,v,cost;bool flag = false;    for(i=E[u];i!=-1;i=buf[i].next){        v=buf[i].b;cost=buf[i].val;        if(v == pre) continue;        dfs(v,u,lim);        flag = true;        if(cost <= lim) dp[u] += min(cost,dp[v]);        else dp[u] += dp[v];    }    if(!flag) dp[u] = INF;}int main(){    int i,a,b,w,lb,rb,mid;    while(scanf("%d%d",&n,&m),n+m){        init();        for(i=1;i<n;i++){            scanf("%d%d%d",&a,&b,&w);            add_edge(a,b,w);        }        lb = 0;rb = INF;        while(rb - lb > 1){            mid=(lb+rb)>>1;            memset(dp,0,sizeof(dp));            dfs(1,-1,mid);            if(dp[1] <= m) rb = mid;            else lb = mid;        }        if(rb == INF) printf("-1\n");        else printf("%d\n",rb);    }    return 0;}


0 0
原创粉丝点击