hdu3586 Information Disturbing(树形dp)

来源:互联网 发布:brew install php扩展 编辑:程序博客网 时间:2024/06/05 14:27

hdu3586

题目

就是给你一棵树,1节点是指挥部,叶子节点是前线士兵,每条边除去有代价,但代价的总和要小于上限m,现要让指挥部和叶子节点失去联系,要使删去的边中最大的最小,问这个最小值是多少。

思路

首先要想到这是一个二分判定性问题,二分上限值,用树形dp进行可行性判断dp[i]表示选i节点花费的最小代价的总和,dp[i]要么加上和子节点相连的那条边,或者是子节点的dp,注意子节点要赋成inf,且wa的可能是inf太大了。。。(竟然二分都要不会写了23333)

代码

#include <cstdio>#include <algorithm>#include <vector>#include <cstring>#include <iostream>#include <stack>#include <queue>using namespace std;typedef long long ll;const int maxn=1100;const int maxm=1000100;int tot,head[maxn],n,m;struct node{    int next;    int to;    int w;} edge[maxn*2];void addedge(int from,int to,int w){    edge[tot].to=to;    edge[tot].next=head[from];    edge[tot].w=w;    head[from]=tot++;}int dp[maxn];int lim;void dfs(int u,int fa){    int cnt=0;    dp[u]=0;    for(int i=head[u]; ~i; i=edge[i].next)    {        int v=edge[i].to;        int w=edge[i].w;        if(v==fa) continue;        cnt++;        dfs(v,u);        if(w<=lim)            dp[u]+=min(w,dp[v]);        else        {            dp[u]+=dp[v];        }    }    if(cnt==0)    {        dp[u]=maxm;    }}int solve(){    memset(dp,0,sizeof(dp));    dfs(1,-1);    if(dp[1]>m) return 0;    return 1;}int main(){    while(scanf("%d %d",&n,&m)!=EOF)    {        if(n==0&&m==0) break;        int maxe=0;        memset(head,-1,sizeof(head));        tot=0;        for(int i=0; i<n-1; i++)        {            int a,b,c;            scanf("%d %d %d",&a,&b,&c);            addedge(a,b,c);            addedge(b,a,c);            maxe=max(maxe,c);        }        int l=1;        int r=maxe;        int mid=(l+r)>>1;        int ans=maxm;        while(l<=r)        {            mid=(l+r)>>1;            lim=mid;            if(solve())            {                r=mid-1;                ans=mid;            }            else                l=mid+1;        }        if(ans==maxm)            printf("-1\n");        else            printf("%d\n",ans);    }    return 0;}
0 0
原创粉丝点击