摘要:
最小生成树算法模板——krusal算法
题目简述:
算法分析:
krusal算法的主要利用了贪心的思想,现将所有边按照权重排序,之后每一次添加一条权值最小的边。由于初始时将图简化为只含有n个点的平凡图,因此新加入的边满足加入后不产生环路。
初始时n个点,每一次加入一条边都会将两个点相连接,这个特性正好满足并查集的特点。因此,krusal的代码实现可以采用并查集算法。
代码以及详细注释:
#include <iostream>
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <queue>
#include <numeric>
#define INF 10000000
#pragma warning(disable:4996)
using namespace std;
struct edge {
int u;
int v;
int w;
};
bool comp(edge& e1, edge& e2)
{
return e1.w < e2.w;
}
class UnionFind {
public:
int count; //种类数
vector<int> root; //保存每一个节点的根节点
UnionFind(int _count = 1) :count(_count)
{
root.resize(_count + 1);
for (int i = 1; i <= _count; ++i)
root[i] = i;
}
//路径压缩
int find(int x) {
return root[x] == x ? root[x] : root[x] = find(root[x]);
}
void Union(int x,int y) {
int rootx = find(x);
int rooty = find(y);
if (rootx != rooty)
root[y] = rootx;
}
};
class Solution {
public:
int cnt = 0;
vector<edge> e;
int n, m;
int count = 0;
int ans = 0;
inline void add_edge(int u, int v, int w) {
cnt++;
e[cnt].u = u;
e[cnt].v = v;
e[cnt].w = w;
}
void krusal() {
cin >> n >> m;
e.resize(m + 1);
for (int i = 0; i < m; ++i)
{
int u, v, w;
cin >> u >> v >> w;
add_edge(u, v, w);
}
sort(e.begin(), e.end(), comp);
UnionFind un(n);
for (int i = 1; i <= m; ++i)
{
int u = un.find(e[i].u);
int v = un.find(e[i].v);
if (u == v)
continue;
ans += e[i].w;
count++;
un.Union(u, v);
}
if (count == n - 1)
cout << ans << endl;
else
cout << "orz" << endl;
}
};
int main() {
//freopen("in.txt", "r", stdin);
Solution s;
s.krusal();
return 0;
}