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;
}