思路和第一篇题解差不多......但只拿到了40pts
求大佬答疑qwq
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 50020;
struct pt{
int s,t,c,col;
}line[maxn];
inline bool cmp(pt a,pt b){return a.c<b.c;}
int faj[maxn];
int n,m,need;
int ans;
int find(int x){
return x==faj[x]?x:faj[x] = find(faj[x]);
}
inline void merge(int x,int y){faj[find(x)] = faj[find(y)];}
void add(int mid){for(int i=1;i<=n;i++)if(line[i].col) line[i].c+=mid;}//通过给黑边加权,控制白边数量
void minus(int mid){for(int i=1;i<=n;i++)if(line[i].col) line[i].c-=mid;}//操作完后还要减回来
int kruskal(int &ans,int mid){
for(int i=1;i<=n;i++) faj[i] = i;
int sum=0,cnt=0;
for(int i=1;i<=m;i++){
int u = line[i].s, v = line[i].t;
if(find(u) != find(v)){
// printf("%d\n",line[i].c);
cnt++;
merge(u,v),ans+=line[i].c;
if(!line[i].col) sum++;
else ans-=mid;
if(cnt==n-1)break;
}
}
return sum;
}
int read(){
int num=0;
char c=getchar();
while(c<'0'||c>'9')c=getchar();
while('0'<=c&&c<='9')num=num*10+c-'0',c=getchar();
return num;
}
int main(){
n=read(),m=read(),need=read();
for(int i=1;i<=m;i++){
line[i].s = read();
line[i].s++;
line[i].t = read();
line[i].t++;
line[i].c = read();
line[i].col = read();
}
int l=-120,r=120;
int ans=0;
while(l<r){
// printf("%d %d\n",l,r);
int mid = (l+r)>>1;
add(mid);
sort(line+1,line+n+1,cmp);
ans=0;
int cnt = kruskal(ans,mid);
if(cnt==need){
printf("%d",ans);
return 0;
}
if(cnt>need) r=mid-1;
else l=mid+1;
minus(mid);
}
printf("%d",ans);
return 0;
}