题意:
分析:
手动给边权赋值,转化成 PP2619 [国家集训队2]Tree I
代码:
#include<bits/stdc++.h>
using namespace std;
namespace zzc
{
const int maxn = 2e4+5;
const int maxm = 100005;
const double eps = 1e-5;
int fa[maxn];
int n,m,need,tot,cnt;
bool vis[maxm];
struct edge
{
int frm,to,nxt,flag;
double val;
}e[maxm];
bool cmp(edge a,edge b)
{
if(a.val==b.val) return a.flag<b.flag;
return a.val<b.val;
}
int find(int u)
{
return fa[u]==u?u:fa[u]=find(fa[u]);
}
void init()
{
scanf("%d%d%d",&n,&m,&need);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&e[i].frm ,&e[i].to,&e[i].flag);
e[i].val=rand()%m;
}
}
void kruskal()
{
sort(e+1,e+m+1,cmp);
for(int i=1;cnt!=n-1;i++)
{
int fx=find(e[i].frm),fy=find(e[i].to);
if(fx!=fy)
{
vis[i]=true;
cnt++;
fa[fx]=fy;
if(e[i].flag==0) tot++;
}
}
}
void solve()
{
double l=-2e5+5,r=2e5+5;
while(r-l>=eps)
{
double mid=(l+r)/2.0;
for(int i=1;i<=m;i++)
{
if(!e[i].flag) e[i].val+=mid;
vis[i]=false;
}
for(int i=1;i<=n+1; i++) fa[i]=i;
cnt=0,tot=0;
kruskal();
if(tot>=need) l=mid+1;
else r=mid-1;
if(tot==need)
{
for(int i=1;i<=m;i++) if(vis[i]) printf("%d %d %d\n",e[i].frm,e[i].to,e[i].flag);
return ;
}
for(int i=1; i<=m; i++) if(e[i].flag==0)e[i].val-=mid;
}
printf("no solution\n");
}
void work()
{
srand(time(0));
init();
solve();
}
}
int main()
{
zzc::work();
return 0;
}