题目链接: 寻宝
上一篇学习了最小生成树的Prim算法,这一篇是对最小生成树 Kruskal 算法的学习。
Prim 算法是维护节点的集合,而 Kruskal 是维护边的集合,kruscal的思路:
- 边的权值排序,因为要优先选最小的边加入到生成树里
- 遍历排序后的边
如果边首尾的两个节点在同一个集合,说明如果连上这条边图中会出现环
如果边首尾的两个节点不在同一个集合,加入到最小生成树,并把两个节点加入同一个集合
在代码实现中使用了 并查集 和 lambda表达式
#include <bits/stdc++.h>
using namespace std;
vector<int> father(10001, -1);
void init(int n) {
for (int i = 0; i <= n; i++) {
father[i] = i;
}
}
int find(int t) {
return t == father[t] ? t : father[t] = find(father[t]);
}
bool isSame(int u, int v){
u = find(u);
v = find(v);
return u == v;
}
void join(int u, int v) {
u = find(u);
v = find(v);
if (u == v){
return;
}
father[v] = u;
}
int main(){
int V, E;
cin >> V >> E;
vector<vector<int>> edges;
int s,t,val;
while(E--){
cin >> s >> t >> val;
edges.push_back({s, t, val});
}
int ans = 0;
init(V);
sort(edges.begin(), edges.end(), [](const vector<int>& edge1, const vector<int>& edge2){
return edge1[2] < edge2[2];
});
for(auto& edge : edges){
if(!isSame(edge[0], edge[1])){
join(edge[0], edge[1]);
ans += edge[2];
}
}
cout << ans << endl;
return 0;
}