1、什么是最小生成树
(1)是一棵树
- 无回路
- |v| 个顶点一定有 |v| - 1条边
(2)是生成树
- 包含全部顶点
- |v| - 1条边都在图里
(3)边的权重和最小
2、Prim算法 – 让一棵小树长大
Prim算法其实就是改进的dijkstra算法。Prim算法是先选择一个点作为源点,然后根据其它点到源点s的最小距离,逐步收录其它顶点。收录的过程是按照顶点来进行收录的。
/*
Prim算法 -- 让一个小树长大,逐步收录每一条最小边
*/
void Prim() {
MTS = {s}; // 随便选择一个点作为源点s,然后收录
while (1) {
v = 未收录顶点中的最小值;
if (v不存在) {
break;
}
将v收录进MTS中,dist[v] = 0;
for (v的每个邻接点w) {
if (dist[w] != 0) {
if (dist[w] > edge[w][v]) {
dist[w] = edge[w][v];
parent[w] = v; // 表示在生成树中,w连接到节点v
}
}
}
}
if (MTS中收录的顶点个数小于|v|) {
cout << "生成树不存在\n";
}
}
2、Kruskal算法 – 将森林合并成树
与Prim算法不同的是,Kruskal算法每次选择的都是边,每次将权重最小的边加入,如果不构成回路,那么就认为是一条有效边。最终判断有效边的数量是否为|v| - 1。
void Kruskal(Graph G) {
MTS = {};
while (MTS中不到|v| - 1条边 && E中还有边) {
从E中选择一条权重最小的边E(v,w); // 可以利用最小堆
将E(v, w)从E中删除;
if (E(v, w)不在MTS中构成回路) // 回路判断:并查集
{
将E(v,w)加入到MTS;
}
}
if (MTS中不到 |v| - 1条边) {
cout << "生成树不存在\n";
}
}