【bzoj2654]】tree

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

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
 
typedef long long LL;
 
#define N 100010
 
struct Node
{
    int x,y,z,c;
}e[N],a[N];
 
int n,m,need;
 
LL ans,cnt,tot;
 
int l,r,mid;
 
int f[N];
 
int cmp(Node a,Node b)
{
    return a.z==b.z ? a.c<b.c : a.z<b.z;
}
 
int find(int x)
{
    return f[x]!=x ? f[x]=find(f[x]) : f[x];
}
 
void kruskal()
{
    cnt=0,ans=0;
    int k=0;
    for (int i=1;i<=n;i++)
        f[i]=i;
    for (int i=1;k<n-1;i++)
    {
        int fa=find(e[i].x);
        int fb=find(e[i].y);
        if (fa!=fb)
        {
            f[fa]=fb;
            ans+=e[i].z;
            k++;
            if (!e[i].c)
                cnt++;  
        }
    }
}
 
int main()
{
    scanf("%d%d%d",&n,&m,&need);
    for (int i=1;i<=m;i++)
        scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].z,&a[i].c),a[i].x++,a[i].y++;
    l=-1010,r=1010;
    while (l<=r)
    {
        mid=(l+r)>>1;
        for (int i=1;i<=m;i++)
            e[i]=a[i];
        for (int i=1;i<=m;i++)
            if (!e[i].c)
                e[i].z-=mid;
        sort(e+1,e+m+1,cmp);
        kruskal();
        if (cnt<need)
            l=mid+1;
        else
            r=mid-1,tot=ans+need*mid;
    }
    printf("%lld\n",tot);
    return 0;
}

  

posted @ 2016-07-23 19:39  Yangjiyuan  阅读(139)  评论(0编辑  收藏  举报