易水人去,明月如霜。
Description
Input
Output
Sample Input
0 1 1 1
0 1 2 0
Sample Output
光光要求有K條白色的邊並不好解決,我們可以思考一下,我們要恰好K條白色的邊,那麼如果給白色的邊都加上一個固定的權值X,我們可以發現,如果X越大,那麼白色邊的數量就越少,對此,我們可以二分一下,加入的權值,求出一個最小的權使得,選擇白色邊的數量恰好爲K
代碼:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#define maxn 100005
using namespace std;
int read()
{
char ch;int s=0,f=1;ch=getchar();
while(ch>'9'||ch<'0') { if(ch=='-') f*=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') s=s*10+ch-48,ch=getchar();
return s*f;
}
struct node {
int u,v,w,c;
}e[maxn];
int u[maxn],v[maxn],w[maxn],c[maxn];
int fa[maxn];
int find(int x)
{
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
bool cmp(const node &a,const node &b)
{
if(a.w==b.w) return a.c<b.c;
else return a.w<b.w;
}
int n,m,k;
int ans;
int nod;
bool check(int x)
{
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++) {e[i].u=u[i],e[i].v=v[i],e[i].w=w[i],e[i].c=c[i]; if(!c[i]) e[i].w+=x; }
sort(e+1,e+1+m,cmp);
ans=0,nod=0;
for(int i=1;i<=m;i++)
{
int r1=find(e[i].u),r2=find(e[i].v);
if(r1!=r2)
{
fa[r1]=r2;
ans+=e[i].w;
if(!e[i].c) nod++;
}
}
ans-=nod*x;
return nod>=k;
}
void work()
{
int anns;
int l=-100,r=100,mid;
while(l<=r)
{
mid=(l+r)/2;
if(check(mid)) l=mid+1,anns=ans;
else r=mid-1;
}
printf("%d",ans);
}
int main()
{
n=read(),m=read(),k=read();
for(int i=1;i<=m;i++) u[i]=read(),v[i]=read(),w[i]=read(),c[i]=read(),u[i]++,v[i]++;
work();
return 0;
}