hdu3586,树形dp+二分

来源:互联网 发布:绿城和万科哪个好 知乎 编辑:程序博客网 时间:2024/05/16 15:54

切断根与叶子结点之间的联系,所有切断的边不能超过一个值k,切断边的总和不能超过m,如果不存在这样的一个k,输出-1,否则输出k。

二分得到k,找到满足条件的最小值

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#define INF 1000001int dp[1005],first[1005],next[2005],mid;struct edge{    int u;    int v;    int w;}en[2005];int min(int a,int b){    return a>b?b:a;}void add(int a,int b,int c,int p){    en[p].u=a;    en[p].v=b;    en[p].w=c;    next[p]=first[a];    first[a]=p;}void getdp(int s,int fu){    int i,flag;    //printf("a%d\n",mid);    flag=0;    for(i=first[s];i!=-1;i=next[i])    {        if(en[i].v!=fu)        {            flag=1;            getdp(en[i].v,s);            if(en[i].w<=mid)            {                dp[s]+=min(dp[en[i].v],en[i].w);            }            else            {                dp[s]+=dp[en[i].v];            }        }    }    if(flag==0)        dp[s]=INF;}int main(){    int n,m,i,j,k,l,le,ri,a,b,c,idx;    while(scanf("%d%d",&n,&m)!=EOF)    {        if(n==0&&m==0)            break;        memset(first,-1,sizeof(first));        memset(next,-1,sizeof(next));        for(i=1,idx=0;i<n;i++)        {            scanf("%d%d%d",&a,&b,&c);            idx++;            add(a,b,c,idx);            idx++;            add(b,a,c,idx);        }        le=0;ri=1000;        while(ri>le)        {            mid=(ri+le)>>1;            memset(dp,0,sizeof(dp));            getdp(1,-1);            if(dp[1]<=m)                ri=mid;            else                le=mid+1;            /*for(i=1;i<=n;i++)                printf("%d ",dp[i]);            printf("\n");*/        }        memset(dp,0,sizeof(dp));        mid=le;        getdp(1,-1);        if(dp[1]<=m)        printf("%d\n",le);        else            printf("-1\n");    }    return 0;}


0 0
原创粉丝点击