zoukankan      html  css  js  c++  java
  • 赛道修建 二分答案

    赛道修建 二分答案

    最小赛道长度的最大值,很明显的二分答案,即求出赛道长度均大于等于(mid)时最多赛道条数,判断是否大于(m)即可。

    但是如何求出最多的条数?我们发现这是一颗树,可以用一种子树递归计算的思路,算出儿子节点的答案来算出父亲节点的答案,每次我们只管算出当前子树,再将一些情况上传到父亲,这是一个很妙的思路。

    具体如何计算当前子树最大赛道数就咕咕咕了,主要是上面的思想

    #include <cstdio>
    #include <set>
    #include <algorithm>
    #define MAXN 50005
    using namespace std;
    int head[MAXN],vv[MAXN*2],ww[MAXN*2],nxt[MAXN*2],tot;
    inline void add_edge(int u, int v, int w){
    	vv[++tot]=v;
    	ww[tot]=w;
    	nxt[tot]=head[u];
    	head[u]=tot;
    }
    multiset <int> s[MAXN];
    multiset <int>::iterator iter;
    int n,m,cnt;
    int solve(int u, int fa, int k){
        s[u].clear();
        for(int i=head[u];i;i=nxt[i]){
            int v=vv[i],w=ww[i];
            if(v==fa) continue;
            int val=w+solve(v, u, k);
            if(val>=k) ++cnt;
            else s[u].insert(val);
        }
        int res=0;
        while(!s[u].empty()){
            if(cnt>=m) return 0;
            int cur=*s[u].begin();
            if(s[u].size()==1) return max(res, cur);
            iter=s[u].lower_bound(k-cur);
            if(iter==s[u].begin()&&s[u].count(*iter)==1) iter++;
            if(iter==s[u].end()){
                res=max(res, cur);
                s[u].erase(s[u].begin());
            }else{
                ++cnt;
                s[u].erase(iter);
                s[u].erase(s[u].begin());
            }
        }
        return res;
    }
    bool check(int k){
        cnt=0;
        solve(1,0,k);
        if(cnt>=m) return 1;
        return 0;
    }
    int main()
    {
        scanf("%d %d", &n, &m);
        int l=1,r=0;
        for(int i=1;i<=n-1;++i){
            int u,v,w;
            scanf("%d %d %d", &u, &v, &w);
            add_edge(u,v,w);
            add_edge(v,u,w);
            r+=w;
        }
        int ans=0;
        while(l<=r){
            int mid=(l+r)>>1;
            if(check(mid)) ans=mid,l=mid+1;
            else r=mid-1;
        }
        printf("%d", ans);
    	return 0;
    }
    
    
  • 相关阅读:
    ThreadLocal内存泄漏真因探究(转)
    JAVA设计模式工厂模式
    java设计模式单例模式
    Java-Socket
    Java-Queue总结
    Java-Reentrantlock
    Java-Iterator遍历集合
    安装和启动docker
    C# System.Reflection.Assembly动态加载资源文件
    C#调用 kernel32.dll
  • 原文地址:https://www.cnblogs.com/santiego/p/11366752.html
Copyright © 2011-2022 走看看