(男神跟我说这题很搞笑.......
二分给白边都加上一个权 不难证明这对MST上白边的数量影响是由二分性的
排序的时候如果权值相等就让白边在前面
这样的话二分出来 记录个数恰好>=need时的答案就可以了
至于为什么 挺值得思考。。 因为保证有解 所以可以让相等权值的黑边代替白边
其它对二分的理解 解释跟上面说的大同小异 可以自己YY一下
其实我不是很会证为什么这样做是对的 以自己的理解讲一下吧
因为kruskal的贪心性保证了最优 所以就用二分来调整MST中白边的个数
#include<bits/stdc++.h>
#define me(a,x) memset(a,x,sizeof a)
using namespace std;
inline int read(){
char ch=getchar(); int x=0;
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0'; ch=getchar();}
return x;
}
struct E{int x,y,c,d;}a[100005];
int Cmp(E x,E y){return x.c!=y.c?(x.c<y.c):(x.d<y.d);}
int n,m,d,f[50005];
inline int fa(int x){return x==f[x]?x:f[x]=fa(f[x]);}
int main()
{
n=read(),m=read(),d=read();
int i,l=-100,r=100;
for(i=1;i<=m;i++)a[i]=(E){read()+1,read()+1,read(),read()};
int ans,s,t,u,x,y;
while(l<=r){
int mid=(l+r)>>1;
for(i=1;i<=n;i++)f[i]=i;
for(i=1;i<=m;i++)if(!a[i].d)a[i].c+=mid;
sort(a+1,a+1+m,Cmp);
s=t=u=0;
for(i=1;i<=m;i++){
x=fa(a[i].x),y=fa(a[i].y);
if(x==y)continue;
t++,f[x]=y,s+=a[i].c,u+=!a[i].d;
if(t==n-1)break;
}
if(u>=d)ans=s-d*mid,l=mid+1; else r=mid-1;
for(i=1;i<=m;i++)if(!a[i].d)a[i].c-=mid;
}
printf("%d\n",ans);
return 0;
}