最小生成树算法
最小生成树——克鲁斯卡尔算法:给定一个有权无向图,求其最小生成树。克鲁斯卡尔算法是最常用的解决方法
题目描述
给定一些边的信息,每条边有一个权值,求由这些边组成的最小生成树的权值和。
答案
使用克鲁斯卡尔算法,先将所有的边按权值从小到大排序,然后对于每条边,判断这两个点是否在同一个连通分量中,若不在则将这条边加入最小生成树,并将这两个点所在的连通分量合并。
代码
以下是使用C++实现克鲁斯卡尔(Kruskal)算法求最小生成树的代码:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
// 定义边的结构体
struct Edge {
int from, to, weight;
};
const int MAXN = 100; // 最大顶点数
int parent[MAXN]; // 父节点数组,用于并查集
vector<Edge> edges; // 存储边的数组
// 并查集查找祖先
int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]);
}
return parent[x];
}
// 克鲁斯卡尔算法求最小生成树
void kruskal(int n) {
sort(edges.begin(), edges.end(), [](Edge a, Edge b) { // 将边按权值从小到大排序
return a.weight < b.weight;
});
for (int i = 0; i < n; i++) { // 初始化并查集
parent[i] = i;
}
for (auto edge : edges) {
int root1 = find(edge.from); // 查找两个顶点所在树的根
int root2 = find(edge.to);
if (root1 == root2) { // 如果已经在同一棵树,则跳过
continue;
}
parent[root1] = root2; // 否则将两棵树合并
cout << "Edge from " << edge.from << " to " << edge.to << " with weight " << edge.weight << endl;
}
}
int main() {
int n; // 顶点数
int m; // 边数
cin >> n >> m;
for (int i = 0; i < m; i++) { // 输入图的边
int from, to, weight;
cin >> from >> to >> weight;
edges.push_back({from, to, weight});
}
kruskal(n);
return 0;
}
在以上代码中,我们首先定义了一个边的结构体Edge,然后按照边的权值从小到大对边进行排序,接着使用并查集来判断两个顶点是否在同一棵树中,若不在,则将它们合并,并输出这个边。最后,我们在main函数中读入输入数据,然后调用kruskal函数求最小生成树。