hdu 3586 Information Disturbing(树形dp)

来源:互联网 发布:sql sum多个字段求和 编辑:程序博客网 时间:2024/05/26 02:20
题意:

给出一棵树,1是根节点,问如果切断边(每个边都有权值)使得总权值小于一个上限up并且小于m,求这样的最小上限up。

题解:

分析这题 要求上限最小无非就是枚举上限(从1-最大边的权值),对于每个上限都dp一次。直接枚举肯定超时,用二分枚举降低复杂度。


#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>#include<math.h>using namespace std;#define oo 1000001#define maxn 1005int dp[maxn];struct Node{    int v,val,next;}E[maxn<<1];int head[maxn],tol;int cost[maxn];void inst(){    memset(head,-1,sizeof head);    tol=0;}void add_edge(int u,int v,int w){    E[tol].v=v;    E[tol].val=w;    E[tol].next=head[u];    head[u]=tol++;}void tree_dp(int u,int pre,int up){    int f=0;    dp[u]=0;    for(int i=head[u];i!=-1;i=E[i].next)    {        int v=E[i].v;        if(v==pre) continue;        tree_dp(v,u,up);        f=1;        if(E[i].val>up)            dp[u]+=dp[v];        else            dp[u]+=min(E[i].val,dp[v]);    }    if(!f) dp[u]=oo;}int main(){    int n,m,maxc;    int u,v,w;    while(scanf("%d %d",&n,&m)!=EOF)    {        if(n==0&&m==0) break;        inst();        maxc=0;        for(int i=1;i<=n-1;i++)        {            scanf("%d %d %d",&u,&v,&w);            add_edge(u,v,w);            add_edge(v,u,w);            maxc=max(maxc,w);        }        int l=1,r=maxc,ans=oo;        while(l<=r)        {            int mid=(l+r)>>1;            tree_dp(1,-1,mid);            if(dp[1]<=m)            {                ans=mid;                r=mid-1;            }            else l=mid+1;        }        if(ans==oo) printf("-1\n");        else printf("%d\n",ans);    }    return 0;}/*5 51 3 21 4 33 5 54 2 60 0*/


0 0