思路:
按边权由小到大合并边的两个顶点,假设当前需要操作的边为,则:
如果已经在同一个组里了就不用继续合并了
如果不在同一个组里,就将所在的组合并,则存在一条路径上的最大值就是,且找不到比其他的路径满足该路径上的最大值小于,因为目前只有这一条路径(边),那么

每一阶段取出同权值的所有边,将这些边的端点用并查集两两合并,待合并完这一阶段的全部边,并查集数量为,那么当前阶段合并边的权值就是答案,否则输出。也就是说同权值的所有边要同时合并,因为未被合并的边的权值需要满足(因为题目要求 之间不可能有任何路径满足该路径中的最大值小于或等于 。)
code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 7,maxm=5e5+7;
int fa[maxn],n,m,k;
set<int>st;
unordered_map<int,int>mp;
vector<pair<int,int> >v[maxm];
inline int find(int x) {
    return x==fa[x]?x:(fa[x]=find(fa[x]));
}
inline void solve() {
    cin>>n>>m>>k;
    int cnt=n,ans=-1,x,y,tot(0);
    for(int i=1;i<=n;++i) fa[i]=i;
    for(auto i:st) v[mp[i]].clear();
    st.clear(); mp.clear();
    for(int i=1,c;i<=m;++i) {
        cin>>x>>y>>c;
        if(!mp.count(c)) mp[c]=++tot;
        st.insert(c);
        v[mp[c]].emplace_back(make_pair(x,y));
    }
    if(n==k) return printf("0\n"),void();
    for(auto i:st) {
        for(auto j:v[mp[i]]) {
            x=find(j.first),y=find(j.second);
            if(x!=y) {
                fa[y]=x; --cnt;
            }
        }
        if(cnt==k) return printf("%d\n",i),void();
        if(cnt<k) return printf("-1\n"),void();
    }
    printf("-1\n");
}
int main() {
//    freopen("1.txt","r",stdin);
//    freopen("brute.txt","w",stdout);
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int T,n,m,k;
    cin>>T;
    while(T--) solve();
    return 0;
}