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);
}

猜你喜欢

转载自www.cnblogs.com/MikuKnight/p/9004228.html