zoukankan      html  css  js  c++  java
  • 洛谷P2619 [国家集训队]Tree I(二分+最小生成树)

    https://www.luogu.com.cn/problem/P2619

    边有黑白两色,求恰好有k条白边的最小生成树

    在克鲁斯卡尔算法中,将边权从小到大排序

    我们可以通过将白边的权值加减,来改变白边在排序中的位置

    假设要求白边用5条,现在是所有白边权值加3

    若求出来白边用了8条,说明权值加小了,白边在前面太多,需要加更多的权值,把一些白边扔到后面

    若求出来白边用了2条,说明权值加大了,前面的白边太少,需要加小些的权值,把一些白边扔到前面

    这样就可以二分进行加权值的调整

    若找到了一个权值,加上之后,白边恰好用了要求的条数,皆大欢喜

    若加权值x,白边使用条数大于要求条数;然而加权值x+1,导致白边使用条数小于要求条数

    这种情况下,存在黑边与加权之后的白边权值相同,这样把白边换成黑边即可

    所以二分过程中,只要使用条数大于等于要求条数,就更新一次答案

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define N 50001
    #define M 100001
    
    int n,m,k;
    struct node
    {
        int u,v,w,c;
    }e[M];
    
    int use,sum;
    
    int fa[N];
    
    bool cmp(node p,node q)
    {
        if(p.w!=q.w) return p.w<q.w;
        return p.c<q.c;
    }
    
    int find(int i) { return fa[i]==i ? i : fa[i]=find(fa[i]); }
    
    void check(int x)
    {
        for(int i=1;i<=m;++i) 
            if(!e[i].c) e[i].w+=x;
        sort(e+1,e+m+1,cmp);
        for(int i=1;i<=n;++i) fa[i]=i;
        int now=0,fu,fv,j=1;
        use=sum=0;
        while(now!=n-1)
        {
            fu=find(e[j].u);
            fv=find(e[j].v);
            if(fu!=fv)
            {
                now++;
                fa[fu]=fv;
                if(!e[j].c) ++use;
                sum+=e[j].w;
            }
            ++j;
        }
        for(int i=1;i<=m;++i) 
            if(!e[i].c) e[i].w-=x;
    }
    
    int main()
    {
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=m;++i) 
        {
            scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].w,&e[i].c);
            ++e[i].u;
            ++e[i].v;
        }
        int l=-101,r=101,mid,ans;
        while(l<=r)
        {
            mid=l+r>>1;
        //    printf("%d ",mid);
            check(mid);
            if(use>=k) 
            {
        //        printf("
    ");
                ans=sum-k*mid;
                l=mid+1;
            } 
            else r=mid-1;
        }
        printf("%d",ans); 
    }
    作者:xxy
    本文版权归作者和博客园共有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。
  • 相关阅读:
    git 强制覆盖本地
    .gitignore 配置
    Git fetch和git pull的区别
    时间函数 date strtotime
    page show
    prepare PDO
    Lucene搜索方法总结
    lucene索引日期和数字
    lucene 3.0.2 + 多文件夹微博数据(时间,微博)构建索引
    lucene 使用注意
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/15131583.html
Copyright © 2011-2022 走看看