# BZOJ 2654: tree【WQS二分+最小生成树】

## 2654: tree

Time Limit: 30 Sec Memory Limit: 512 MB

Description

Input

Output

V<=50000,E<=100000,所有数据边权为[1,100]中的正整数。

Sample Input

2 2 1
0 1 1 1
0 1 2 0

Sample Output

2

HINT

#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,e,ans,alc,fa[50005];
struct xcw{
int x,y,w,c;
bool operator <(const xcw b)const{return (w<b.w)||(w==b.w&&c<b.c);}
}a[100005],E[100005];
int get(int x){return fa[x]==x?x:fa[x]=get(fa[x]);}
bool check(int x){
int num;alc=num=0;
for(int i=0;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++){
E[i]=a[i];
if(!E[i].c) E[i].w+=x;
}
sort(E+1,E+1+m);
for(int i=1;i<=m;i++){
int fx=get(E[i].x),fy=get(E[i].y);
if(fx^fy){
fa[fy]=fx,alc+=E[i].w;
if(!E[i].c) num++;
}
}
return num>=e;
}
int main(){
//  freopen("prob.in","r",stdin);
//  freopen("prob.out","w",stdout);
scanf("%d%d%d",&n,&m,&e);
for(int i=1;i<=m;i++) scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].w,&a[i].c);
for(int L=-105,R=105,mid=(R+L)>>1;L<=R;mid=(R+L)>>1)
if(check(mid)) L=mid+1,ans=alc-mid*e;else R=mid-1;
printf("%d\n",ans);
return 0;
}