wqs二分
首先二分一个白边所加的权值
然后根据当前MST(若黑白边权值相同则优先选白边)中白边的数目二分
若白边数过多,则增加所加的值
若白边数过少,则减小所加的值
/**************************************************************
Problem: 2654
User: syh0313
Language: C++
Result: Accepted
Time:3236 ms
Memory:3244 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using
namespace
std;
const
int
maxn=100010;
int
n,m,k,ans,sum,fa[maxn];
struct
da{
int
fr,to,w,col;}a[maxn];
bool
cmp(da aa,da bb)
{
if
(aa.w==bb.w)
return
aa.col<bb.col;
return
aa.w<bb.w;
}
int
getf(
int
x)
{
if
(x==fa[x])
return
x;
fa[x]=getf(fa[x]);
return
fa[x];
}
int
ok(
int
x)
{
for
(
int
i=1;i<=m;i++)
if
(!a[i].col) a[i].w+=x;
for
(
int
i=1;i<=n;i++) fa[i]=i;
sort(a+1,a+m+1,cmp); sum=0;
int
cnt=0;
for
(
int
i=1;i<=m;i++)
{
if
(getf(a[i].fr)==getf(a[i].to))
continue
;
fa[getf(a[i].fr)]=getf(a[i].to);
sum+=a[i].w;
if
(!a[i].col) cnt++;
}
for
(
int
i=1;i<=m;i++)
if
(!a[i].col) a[i].w-=x;
return
cnt;
}
int
main()
{
scanf
(
"%d%d%d"
,&n,&m,&k);
for
(
int
i=1;i<=m;i++)
scanf
(
"%d%d%d%d"
,&a[i].fr,&a[i].to,&a[i].w,&a[i].col),a[i].fr++,a[i].to++;
int
l=-100,r=100;
while
(l<=r)
{
int
mid=(l+r)>>1;
int
num=ok(mid);
if
(num>=k) ans=sum-k*mid,l=mid+1;
else
r=mid-1;
}
printf
(
"%d\n"
,ans);
return
0;
}