[bzoj2654] tree

来源:互联网 发布:方舟生存进化淘宝 编辑:程序博客网 时间:2024/05/29 13:09

题目链接

题解:边权非常小,可以给每条白边都加一个值,随着值的增大,MST中的白边不增,满足单调性,然后就可以二分了

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>using namespace std;int n,m,cnt,tot,ned;int sumv,l=-1000,r=1000;int f[100005];struct edge{    int u,v,w,c;}e[100005];int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}int fd(int x){    return f[x]==x?x:f[x]=fd(f[x]);}bool cmp(edge a,edge b){    return a.w<b.w||(a.w==b.w&&a.c<b.c);}bool check(int x){    tot=cnt=0;    for(int i=1;i<=n;i++)f[i]=i;    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<=m;i++)    {        int p=fd(e[i].u),q=fd(e[i].v);        if(p!=q)        {            f[p]=q;            tot+=e[i].w;            if(!e[i].c)cnt++;        }    }    for(int i=1;i<=m;i++)    if(!e[i].c)e[i].w-=x;    return cnt>=ned;//因可能出现mid+1比ned少,mid比ned大的情况,看似无法处理    //但是若出现,一定有许多相等的白,黑边,可以把一部分白边换成黑边,所以在cnt>=ned时更新}void init(){    cin>>n>>m>>ned;    for(int i=1;i<=m;i++)    e[i].u=read(),e[i].v=read(),e[i].w=read(),e[i].c=read(),e[i].u++,e[i].v++;}void work(){    while(l<=r)    {        int mid=(l+r)>>1;        if(check(mid))l=mid+1,sumv=tot-ned*mid;        else r=mid-1;    }    printf("%d",sumv);}int main(){    init();    work();    return 0;}
0 0