• HDOJ 3586 Information Disturbing(二分答案+树DP)


    题意:给一棵带权有根树,边权表示切断此边的代价,现有一台切边的机器,但它有一个上限值up limited power,只能切断边权不超过up limited power的边,现要切断根节点与所有叶子结点的联系,总代价即为所切边的边权和,给定最大代价m,求最小的up limited power。

    数据范围:n<=1000,m<=1000000,1<=边权wi<=1000

    分析:二分答案,然后树DP判断。复杂度为O(NlogW)

    View Code
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 1001
    int n,m,e;
    int first[N],next[N<<1],v[N<<1],w[N<<1],d[N];
    int dp[N];
    void init()
    {
        e=0;
        memset(first+1,-1,sizeof(first[0])*n);
        memset(d+1,0,sizeof(d[0])*n);
    }
    void add(int a,int b,int c)
    {
        d[a]++;
        v[e]=b;
        w[e]=c;
        next[e]=first[a];
        first[a]=e++;
    }
    void dfs(int a,int fa,int up)
    {
        if(d[a]==1 && v[first[a]]==fa)
        {
            dp[a]=-1;
            return;
        }
        int i,b;
        for(i=first[a];~i;i=next[i])
        {
            b=v[i];
            if(b==fa)    continue;
            dfs(b,a,up);
            if(dp[a]==-1)   continue;
            if(dp[b]==-1 && w[i]>up)
            {
                dp[a]=-1;
            }
            else if(dp[b]!=-1 && w[i]<=up)
            {
                dp[a]+=min(w[i],dp[b]);
            }
            else if(dp[b]!=-1)
            {
                dp[a]+=dp[b];
            }
            else
            {
                dp[a]+=w[i];
            }
        }
    }
    bool judge(int up)
    {
        memset(dp+1,0,sizeof(dp[0])*n);
        dfs(1,0,up);
        if(dp[1]<0 || dp[1]>m)  return 0;
        return 1;
    }
    int main()
    {
        while(scanf("%d%d",&n,&m),(n|m))
        {
            if(n==1)
            {
                puts("0");
                continue;
            }
            int a,b,c,maxw=0;
            init();
            for(int i=1;i<n;i++)
            {
                scanf("%d%d%d",&a,&b,&c);
                add(a,b,c);
                add(b,a,c);
                maxw=max(maxw,c);
            }
            if(judge(maxw)==0)
            {
                puts("-1");
                continue;
            }
            a=0,b=maxw;
            while(a+1!=b)
            {
                c=a+b>>1;
                if(judge(c))    b=c;
                else    a=c;
            }
            printf("%d\n",b);
        }
        return 0;
    }
  • 相关阅读:
    [Leetcode]480. Sliding Window Median
    C++的一些小的知识点
    extern关键字
    c++的默认构造函数 VS 深拷贝(值拷贝) 与 浅拷贝(位拷贝)
    inline-内联函数的优点以及与宏定义的区别
    char类型输出地址
    c++ 对象的内存布局
    Shell 去掉文本中的空格
    牛客网-网易编程题 双端队列找规律
    计算机网络概观
  • 原文地址:https://www.cnblogs.com/algorithms/p/2687348.html
Copyright © 2020-2023  润新知