先用实边跑生成树,然后剩下的连接各个连通块的虚边是一定要选的,重置并查集,把必选的虚边都选上,因为那些连通块用实边就能联通,所以再随便加虚边也无所谓,加虚边到k条,剩下的再用实边做
无解就是必选的虚边大于k条或者无法补齐至k条
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
using namespace std;
#define MAXN 20010
#define MAXM 100010
#define ll long long
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
int f[MAXN];
int i;
int n,m,k;
int v1[MAXM],v2[MAXM],v[MAXM];
bool csn[MAXM];
int fa(int x){
return f[x]==x?x:f[x]=fa(f[x]);
}
void init(){
int i;
for(i=1;i<=n;i++){
f[i]=i;
}
}
int main(){
int i,x,y;
scanf("%d%d%d",&n,&m,&k);
int tot=0;
for(i=1;i<=m;i++){
scanf("%d%d%d",&v1[i],&v2[i],&v[i]);
tot+=v[i]^1;
}
if(tot<k){
printf("no solution\n");
return 0;
}
init();
for(i=1;i<=m;i++){
if(v[i]){
x=v1[i],y=v2[i];
if(fa(x)!=fa(y)){
f[fa(x)]=fa(y);
}
}
}
for(i=1;i<=m;i++){
if(!v[i]){
x=v1[i],y=v2[i];
if(fa(x)!=fa(y)){
f[fa(x)]=fa(y);
csn[i]=1;
k--;
}
}
}
if(k<0){
printf("no solution\n");
return 0;
}
init();
for(i=1;i<=m;i++){
if(csn[i]){
x=v1[i],y=v2[i];
f[fa(x)]=fa(y);
}
}
for(i=1;i<=m;i++){
if(!v[i]&&k){
x=v1[i],y=v2[i];
if(fa(x)!=fa(y)){
f[fa(x)]=fa(y);
csn[i]=1;
k--;
}
}
}
if(k){
printf("no solution\n");
return 0;
}
for(i=1;i<=m;i++){
if(v[i]){
x=v1[i],y=v2[i];
if(fa(x)!=fa(y)){
f[fa(x)]=fa(y);
csn[i]=1;
}
}
}
for(i=1;i<=m;i++){
if(csn[i]){
printf("%d %d %d\n",v1[i],v2[i],v[i]);
}
}
return 0;
}
/*
5 7 2
1 3 0
4 5 1
3 2 0
5 3 1
4 3 0
1 2 1
4 2 1
*/