Kruskal算法求最小生成树
数据达到了n<=1e5 m<=2e5 kruskal牛逼的地方也是直接用结构体去存数据
算法的流程:
1、按照权值从小到大排序
2、枚举每条边a b 权重是c 如果当前a 和 b 不连通的话 把这条边加入到集合里面
这里利用了并查集的
3、初始化 p[i]=i 之前每个结点的父节点都是它本身
4、枚举每个结点
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, m;
string s;
int p[N];
struct ty {
int x, y, v;
}a[N * 2];
bool cmp(ty a, ty b) {
return a.v < b.v;//按照边长权重 从小到大排序
}
int find(int x) {//并查集 路径压缩 几乎是O(1)的
if(x != p[x]) p[x] = find(p[x]);
return p[x];
}
int Kruskal() {
int ret = 0, t = 0;
for(int i = 1; i <= m; ++ i ) {
int pa = find(a[i].x), pb = find(a[i].y);
if(pa != pb) {
p[pa] = pb;
ret += a[i].v;
t++;
}
}
if(t < n - 1)return 0x3f3f3f3f;//加入到集合里面的个数 小于n - 1 n个点生成树需要n-1个点进来
return ret;
}
signed main() {
//数据范围n和m差别不大 Kruskal算法 时间复杂度O(mlogn) 花在了排序上面
cin >> n >> m;
for(int i = 1; i <= n; ++ i )p[i] = i;
for(int i = 1; i <= m; ++ i ) {
int x, y, v;
cin >> x >> y >> v;
a[i] = {x, y, v};
}
sort(a + 1, a + m + 1, cmp);//
int t = Kruskal();
if(t == 0x3f3f3f3f)cout << "impossible" << endl;
else cout << t << endl;
return 0;
}