点击这里查看原题
由题目要求可知,最终得到的图是一棵树。因为要求类型为0的边恰好有k条,所以先对类型为1的边做生成树,再对类型为0的边做,得到必须有的0边。将这些0边加入,然后优先做类型为0的边,再做类型为1的边即可
/*
User:Small
Language:C++
Problem No.:3624
*/
#include<bits/stdc++.h>
#define ll long long
#define inf 999999999
using namespace std;
const int M=1e5+5,N=2e4+5;
int n,m,k,tp,s[N],u[M],v[M],c[M],num[2],pre[N];
bool mark[M];
int find(int x){
return x==pre[x]?x:pre[x]=find(pre[x]);
}
void solve(bool typ,int cnt){
for(int i=1;i<=m;i++){
if(c[i]==typ&&num[typ]<cnt){
int p=find(u[i]),q=find(v[i]);
if(p==q) continue;
pre[p]=q;
num[typ]++;
s[++tp]=i;
mark[i]=1;
}
}
}
int main(){
freopen("data.in","r",stdin);//
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&u[i],&v[i],&c[i]);
for(int i=1;i<=n;i++) pre[i]=i;
solve(1,inf);solve(0,inf);
if(num[0]+num[1]!=n-1||num[0]>k){
printf("no solution\n");
return 0;
}
tp=num[0]=num[1]=0;
for(int i=1;i<=n;i++) pre[i]=i;
for(int i=1;i<=m;i++){
if(c[i]==0&&mark[i]){
int p=find(u[i]),q=find(v[i]);
if(p==q) continue;
pre[p]=q;
s[++tp]=i;
num[0]++;
}
}
solve(0,k);solve(1,inf);
if(num[0]<k){
printf("no solution\n");
return 0;
}
for(int i=1;i<=tp;i++)
printf("%d %d %d\n",u[s[i]],v[s[i]],c[s[i]]);
return 0;
}