• bzoj2654


    给白色边都加上一个值,做kruskal会使得选取的白边数量减少,二分它

    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    using namespace std;
    struct data{int u,v,w,col;}edge[100002],e[100002];
    int n,m,ned,cnt,fa[100002];
    unsigned int sumv,ans;
    
    inline void read(int &x){
        char ch=getchar();x=0;int f=1;
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        x*=f;
    }
    
    bool operator<(data a,data b){
        return a.w==b.w?a.col<b.col:a.w<b.w;
    }
    int findfa(int x){
        if(fa[x]==x)return x;return fa[x]=findfa(fa[x]);
    }
    
    bool check(int x){
        sumv=cnt=0;
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<=m;i++){e[i]=edge[i];if(!e[i].col)e[i].w+=x;}
        sort(e+1,e+m+1);
        for(int i=1;i<=m;i++){
            int p=findfa(edge[i].u),q=findfa(edge[i].v);
            if(p!=q){
                fa[p]=q;
                sumv+=e[i].w;
                if(!e[i].col)cnt++;
            }
        }
        return cnt>=ned;
    }
    
    int main(){
        read(n);read(m);read(ned);
        for(int i=1;i<=m;i++){
            read(edge[i].u);read(edge[i].v);read(edge[i].w);read(edge[i].col);
            edge[i].u++;edge[i].v++;
        }
        int l=-102,r=102;
        while(l<=r){
            int mid=(l+r)>>1;
            if(check(mid)){l=mid+1;ans=sumv-ned*mid;}else r=mid-1;
        }
        printf("%d",ans);
    }
  • 相关阅读:
    Lambda表达式
    java中解决小数精度问题
    [Unity]-黑魂复刻-动画 001
    kuka Virtual Remote pendant 连接使用
    C# 操作 pg 数据库
    C#常用字符串操作
    Go学习笔记之相关资源
    Go学习笔记之常用命令
    Go学习笔记之安装
    nginx学习笔记之安装
  • 原文地址:https://www.cnblogs.com/MikuKnight/p/9004228.html
Copyright © 2020-2023  润新知