code by virtualtan 寒七
/最小生成树:找出最小路径/ /n个数 化成树 边权最小/
/krus…卡尔? 假设他们都没相连,然后…思想:贪心/
重点:并查集(俗称:找爸爸)
#include <cstdio>
#include <algorithm>
#define MAXN 111111
#define MAXM 222222
int n, m, cnt, ans;
int fa[MAXN];
struct edge {
int x, y, val;
}e[MAXM];
bool comp(edge x, edge y) {
return x.val < y.val;
}
//并查集
int father(int x) {
if(fa[x] == x) return x;
return fa[x] = father(fa[x]); //**路径压缩** :就是每次在查找时,令查找路径上的每个节点都直接指向根节点
}
int main() {
for(int i = 1 ; i <= m ;i++) fa[i] = i;//**并查集初始化**为自身(自己单独组成集合)
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++) {
scanf("%d%d%d", &e[i].x, &e[i].y, &e[i].val);
}
std::sort(e + 1, e + 1 + m, comp);//把权排序
for(int i = 1; i <= m; i++) {
int x = e[i].x, y = e[i].y, val = e[i].val;
//并查集:选边时,看它的两端点是不是在同一个集合里(判断这条边的两端点是否直接或间接相连)
// 如果在,则不能构成树( n个数 有n-1条线)
int fax = father(x), fay = father(y); //找根节点
if(fax != fay) {//根节点不相同表示不在同一个集合
ans += val; //选中这条边
fa[fax] = fay; //**将根节点相连,使他们构成一个集合**(加入这条边的时候,将根结点相连,数也就连到一起了;应该也可以写成fa[fax] = fa[fay])
}
}
}
/*
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
*/