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

    题目链接:https://www.luogu.com.cn/problem/P5021

    分析:

    题目大意就不讲了。此题很多人说一眼就知道是二分,那就当我也这么认为吧。此题思考的关键在于不能重边。先设二分的值为k,我们思考一个状态:此时搜到一个点,暂时不考虑下面回溯上来的值,当该值加上其对应的边权大于等于k,则直接统计到答案里,剩余的不满k的值先存起来。我们知道剩余的这些边中还是会存在满足大于等于k的情况,只要任意两条加在一起大于等于k就可以计入答案。(记住这里要用贪心,即对于每条边选择可行方案里最小的)接下来同样按着贪心,选择一条剩余边里最大的一条回溯上去,该值即上文回溯上来的值。看不懂的看代码食用更佳哦!

    补充:代码里用到了set库里的multiset,这里使用能更佳方便地实现代码,不会的建议了解一下。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<set>
    using namespace std;
    #define int long long
    #define R register
    inline int read(){
        int a=0,b=1;char c=getchar();
        while(!isdigit(c)){if(c=='-')b=-1;c=getchar();}
        while(isdigit(c)){a=a*10+c-'0';c=getchar();}
        return a*b;
    }
    multiset<int>::iterator it;
    const int N=5e4+50,M=2e5+50;
    int n,m,tot,cnt,h[N],ver[M],nx[M],ed[M],ave,l,r,ans;
    void add(int u,int v,int z){
        ver[++tot]=v;ed[tot]=z;
        nx[tot]=h[u];h[u]=tot;
    }
    int dfs(int x,int fa,int kkk){
        multiset<int>s;
        for(R int i=h[x],dis;i;i=nx[i]){
            int v=ver[i],z=ed[i];
            if(v==fa)continue;
            dis=z+dfs(v,x,kkk);
            if(dis>=kkk)cnt++;
            else s.insert(dis);
        }
        int maxn=0;
        while(s.size()){
            int p=*s.begin();
            s.erase(s.begin());
            it=s.lower_bound(kkk-p);
            if(it!=s.end()){
                cnt++;
                s.erase(it);
            }
            else{
                maxn=max(maxn,p);
            }
        }
        return maxn;
    }
    bool check(int kkk){
        cnt=0;
        dfs(1,0,kkk);
        if(cnt>=m)return true;
        else return false;
    }
    signed main(){
        n=read();m=read();
        int u,v,z;
        for(R int i=1;i<n;i++){
            u=read();v=read();z=read();
            add(u,v,z);add(v,u,z);
            ave+=z;
        }
        ave/=m;
        l=1,r=ave;
        int mid;
        while(l<=r){
            mid=(l+r)>>1;
            if(check(mid))ans=mid,l=mid+1;
            else r=mid-1;
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    Static Fields and Methods
    usermod
    理解Java的Class类、"this."关键字、Constructor构造器(一)
    [REPRINT] Java 101: Classes and objects in Java
    第六章 Java并发容器和框架
    第五章 Java中锁
    第四章 Java并发编程基础
    第三章 Java内存模型(下)
    第三章 Java内存模型(上)
    第二章 并发机制的底层实现原理
  • 原文地址:https://www.cnblogs.com/zjy1412/p/13517689.html
Copyright © 2011-2022 走看看