题目:
题意:
总共有
n
n
n 个点,
m
m
m条边,要分成
k
k
k 组,满足
( 1 ) (1) (1) 如果顶点 p 和 q ( p ≠ q ) 在同一组中,则 p 和 q 之间必须至少有一条路径满足该路径中的最大值小于或等于 D。
( 2 ) (2) (2) 如果顶点 p 和 q ( p ≠ q ) 在不同的组中,则 p 和 q 之间不可能有任何路径满足该路径中的最大值小于或等于 D。
题解:
最开始分为
c
n
t
=
n
cnt=n
cnt=n个组
按找点的边权从小到大排序, 如果这两个点不在同一个集合中,则将它们合并到一个集合中,同时 c n t − = 1 cnt-=1 cnt−=1,(减少了只有一个点的组), 当 c n t = k cnt=k cnt=k的时候, D D D为当前的边权值,否则为 − 1 -1 −1
注意为了满足要求(2),只有当当前边权不等于上一个边权的时候才判断 c n t cnt cnt是否等于 k k k
#include <bits/stdc++.h>
using namespace std;
struct node {
long long u,v,w;
}e[500005];
int p[100005];
bool cmp(node a,node b)
{
return a.w<b.w;
}
int find(int x)
{
if(p[x]!=x) p[x]=find(p[x]);
return p[x];
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--)
{
int n,m,k;
cin>>n>>m>>k;
int ans=0;
int con=n;
for(int i=1;i<=n;i++) p[i]=i;
for(int i=1;i<=m;i++)
{
cin>>e[i].u>>e[i].v>>e[i].w;
}
sort(e+1,e+1+m,cmp);
for(int i=1;i<=m;i++)
{
if(e[i].w!=e[i-1].w)//满足要求(2)
{
if(con==k)
{
break;
}
}
int pa=find(e[i].u);
int pb=find(e[i].v);
if(pa==pb) continue;
con--;
p[pa]=pb;
ans=e[i].w;//D为当前的边权值
}
if(con==k) cout<<ans<<endl;
else cout<<-1<<endl;
}
return 0;
}