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