思考过程&具体做法:
首先将所有边的价格从小到大排序,然后二分答案,并查集维护是否连通来检验即可。
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e4+1000;
struct stu
{
int x,y,type,cost,id;
}len[maxn*2],now[maxn],ans1[maxn];
int l,r,ans,n,k,m;
int fa[maxn];
bool cmp(stu t1,stu t2)
{
return t1.cost<t2.cost;
}
int find(int x)
{
if(x==fa[x]) return x;
return fa[x]=find(fa[x]);
}
bool judge(int x)
{
int cnt=0;
for(int i=1;i<=x;i++)
{
if(len[i].type==1)
{
int x=len[i].x,y=len[i].y;
int p=find(x),q=find(y);
if(p!=q)
{
fa[p]=q;
cnt++;
now[cnt].id=len[i].id;
now[cnt].type=1;
}
}
}
if(cnt<k) return 0;
for(int i=1;i<=x;i++)
{
int x=len[i].x,y=len[i].y;
int p=find(x),q=find(y);
if(p!=q)
{
fa[p]=q;
cnt++;
now[cnt].id=len[i].id;
now[cnt].type=2;
}
}
if(cnt!=n-1) return 0;
return 1;
}
bool cmp1(stu t1,stu t2)
{
return t1.id<t2.id;
}
int main()
{
scanf("%d%d%d",&n,&k,&m);
m--;
for(int i=1;i<=m;i++)
{
int x,y,a,b;
scanf("%d%d%d%d",&x,&y,&a,&b);
len[i*2-1].x=x;
len[i*2-1].y=y;
len[i*2-1].type=1;
len[i*2-1].cost=a;
len[i*2-1].id=i;
len[i*2].x=x;
len[i*2].y=y;
len[i*2].type=2;
len[i*2].cost=b;
len[i*2].id=i;
}
sort(len+1,len+1+2*m,cmp);
l=1,r=2*m;
while(l<=r)
{
int mid=(l+r)>>1;
for(int i=1;i<=n;i++) fa[i]=i;
bool k=judge(mid);
if(k)
{
ans=len[mid].cost;
for(int i=1;i<=n-1;i++) ans1[i]=now[i];
r=mid-1;
}
else l=mid+1;
}
sort(ans1+1,ans1+n,cmp1);
printf("%d\n",ans);
for(int i=1;i<=n-1;i++) printf("%d %d\n",ans1[i].id,ans1[i].type);
return 0;
}