859.Kruskal最小生成树
思路
从原本算法入手,Kruskal算法是从添加边的角度出发,适合求稀疏图的最小生成树。也就是将边权最小的点的加入到集合当中,所以可以想到思路是:
- 按照边权将边排序(升序)
- 按照边权从小到大选择边,每一条边所连接的两个点可以表示一个集合,当两条边上的节点要相连时,本质上就是集合合并问题。假设:1,3 节点所连接的边和 2,4 所连接的边。当前需要将 2 和 3 连接起来,相当于就是集合{1,3}和集合{2,4}要进行合并,所以可以使用并查集进行合并。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, M = 2e5 + 10;
int p[N];
int n, m;
struct Edge {
int u;
int v;
int w;
bool operator< (const Edge &E) const {
return w < E.w;
}
} e[M];
int find(int x) {
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) p[i] = i;
for (int i = 0; i < m; i++) {
cin >> e[i].u >> e[i].v >> e[i].w;
}
sort(e, e + m);
int res = 0, cnt = 0;
for (int i = 0; i < m; i++) {
int u = e[i].u, v = e[i].v, w = e[i].w;
u = find(u), v = find(v);
if (u != v) {
p[u] = v;
res += w;
cnt ++;
}
}
if (cnt < n -1) cout << "impossible" << endl;
else cout << res << endl;
return 0;
}