HDOJ6958KD-Graph(并查集)
Posted 小哈里
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDOJ6958KD-Graph(并查集)相关的知识,希望对你有一定的参考价值。
1009 KD-Graph
题意:
- 给出一张n个点m条边的加权无向图和一个整数K,求一个数字D可以将图分为K组,组内任意两点存在路径且小于等于D,组外不存在小于等于D的路径。不存在D输出-1。
思路:
- 将边按权值从小到大排序,每一阶段取出同权值的所有边,将这些边的端点用并查集两两合并,若某一阶段的全部边合并完,并查集数量为k,则当前阶段合并边的权值就是答案,否则输出-1。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 3e6+10;
struct Edge{int u,v,w;}e[maxn];
bool cmp(Edge a, Edge b){return a.w<b.w;}
int fa[maxn+10];
void init(int n){for(int i = 0; i <= n; i++)fa[i]=i;}
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
void merge(int x, int y){x=find(x);y=find(y);if(x!=y)fa[x]=y;}
int count(int n){int cnt=0; for(int i = 1; i <= n; i++)if(fa[i]==i)cnt++;return cnt;}
int main(){
ios::sync_with_stdio(false);
int T; cin>>T;
while(T--){
int n, m, k; cin>>n>>m>>k;
for(int i = 1; i <= m; i++)
cin>>e[i].u>>e[i].v>>e[i].w;
init(n);
sort(e+1,e+m+1,cmp);
int now = n, ans = 0, ok = 0; //now表示刚开始有n组(当前并查集个数)
for(int i = 1; i <= m; i++){
if(e[i].w != e[i-1].w){
if(now==k){//直到分成k组,此时的最大ans满足组外不存在小于等于它的路径
cout<<ans<<"\\n";
ok = 1;
break;
}
}
//如果两点间已经有更小的路径就不管
if(find(e[i].u)==find(e[i].v))continue;
//用这条边去合并,将合并的点放入同一组
merge(e[i].u, e[i].v);
now--;//组数-1(并查集个数-1)
ans = e[i].w; //组内<=D(不断变大)
}
if(ok==0)cout<<(now==k?ans:-1)<<"\\n";
}
return 0;
}
以上是关于HDOJ6958KD-Graph(并查集)的主要内容,如果未能解决你的问题,请参考以下文章
2021“MINIEYE杯”中国大学生算法设计超级联赛 6958. KD-Graph