克鲁斯卡尔算法简介
克鲁斯卡尔算法是求连通网的最小生成树的另一种方法。与普里姆算法不同,它的时间复杂度为O(eloge)(e为网中的边数),所以,适合于求边稀疏的网的最小生成树。
克鲁斯卡尔算法基本思想
克鲁斯卡尔(Kruskal)算法从另一途径求网的最小生成树。其基本思想是:假设连通网G=(V,E),令最小生成树的初始状态为只有n个顶点而无边的非连通图T=(V,{}),概述图中每个顶点自成一个连通分量。在E中选择代价最小的边,若该边依附的顶点分别在T中不同的连通分量上,则将此边加入到T中;否则,舍去此边而选择下一条代价最小的边。依此类推,直至T中所有顶点构成一个连通分量为止 。
克鲁斯卡尔算法复杂度
克鲁斯卡尔算法的时间复杂度主要由排序方法决定,而克鲁斯卡尔算法的排序方法只与网中边的条数有关,而与网中顶点的个数无关,当使用时间复杂度为O(elog2e)的排序方法时,克鲁斯卡尔算法的时间复杂度即为O(log2e),因此当网的顶点个数较多、而边的条数较少时,使用克鲁斯卡尔算法构造最小生成树效果较好。
代码示例
输入样例:
6 9
1 2 1
1 3 3
1 4 2
2 5 7
3 4 4
3 5 6
3 6 4
4 6 4
5 6 5
输出样例:
15
代码:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 2e5 + 10;
int n, m, fa[5050];
struct edge {
int u, v, w;
} e[N];
bool cmp(edge a, edge b) {
return a.w < b.w;
}
int find(int x) {
if (fa[x] == x)
return x;
fa[x] = find(fa[x]);
return fa[x];
}
int main() {
cin >> n >> m;
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 <= n; i++)
fa[i] = i;
int cnt = 0, ans = 0;
for (int i = 1; i <= m; i++) {
int fx = find(e[i].u);
int fy = find(e[i].v);
if (fx != fy) {
fa[fx] = fy;
ans += e[i].w;
cnt++;
if (cnt == n - 1)
break;
}
}
cout << ans;
return 0;
}