HDU 3586 Information Disturbing

题目传送门

中文翻译:

给定一颗无向带权树,要切断所有叶子节点和根节点的联系,每次切断的费用不能超过上限 Limit,问在保证 总费用 <=m 的情况下最小的 Limit

解题思路:

f[i]表示以i为根的树的最佳答案,加二分答案.

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

long long n,m,head[1001],tot,MAX,l = 1,ans,f[1001];
struct kkk{
    int to,v,next;
}e[1001];

inline void add(int x,int y,int z) {
    e[++tot].v = z;
    e[tot].to = y;
    e[tot].next = head[x];
    head[x] = tot;
}

inline void dfs(int u,int limit) {
    bool flag = 0;
    f[u] = 0;
    for(int i = head[u];i != 0; i = e[i].next) {
        flag = 1;
        int p = e[i].to;
        dfs(p,limit);
        if(e[i].v <= limit)    
            f[u] += min(f[p],(long long)e[i].v);
        else
            f[u] += f[p];
    }
    if(!flag)
        f[u] = 0x3f3f3f;//如果用int,此处会加爆,所以要用long long 
}

int main() {
    while(scanf("%lld%lld",&n,&m) != EOF) {
        MAX = 0;l = 1;
        if(n == 0 && m == 0) return 0;
        memset(head,0,sizeof(head));
        tot = 0;
        for(int i = 1;i < n; i++) {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);
            MAX = max(MAX,(long long)z);
        }
        ans = -1;
        while(l <= MAX) {
            int mid = (l + MAX) >> 1;
            dfs(1,mid);
            if(f[1] <= m) {
                ans = mid;
                MAX = mid - 1;
            }
            else
                l = mid + 1;
        }
        printf("%lld
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/lipeiyi520/p/12215799.html