最小生成树: 是在一个给定的无向图G(V,E)中求一棵树T,使得这棵树拥有图G中的所有顶点,且所有边都是来自图G中的边,并且满足整棵树的边权之和最小。
最小生成树的性质:
- 最小生成树是树.边数是点数减1.树中不存在环.
- 最小生成树不唯一.但是权值一定相同.
- 根节点可以是任意一个节点.
基本思想
- 对图G(V,E)设置集合S,存放已经被访问的顶点,然后每次从集合V-S中选择与集合S的最短距离最小的一个顶点(记为u),访问并加入集合S。
- 之后,令顶点u为中介点,优化所有从u能到达的顶点v与集合S之间的最短距离。
- 这样的操作执行n次(n为顶点个数),直到集合S已包含所有顶点。
邻接矩阵实现的Prim算法
/*
n 顶点数
s 源点
G 图的邻接矩阵
visited 是否被访问.就是加入集合S中
d 存储顶点和几何S的最短距离
*/
int Prim(int n, int s, vector<vector<int>> G,
vector<bool>& visited, vector<int> &d) {
// 初始化为最大值
fill(d.begin(), d.end(), INT_MAX);
d[s] = 0; // 表示把源点放入集合S中.
int sum = 0; // 最小生成树的权之和
// 循环n次依次找到n个点
for (int i = 0; i < n; i++) {
int u = -1; // u点: V中的u到S的距离最小
int MIN = INT_MAX; // 最小的距离是多少d[u]
// 找到最小值d[j]
for (int j = 0; j < n; j++) {
// 没有遍历过
if (visited[j] == false && d[j] < MIN) {
MIN = d[j];
u = j;
}
}
// 如果找不到d[j],说明不连通
if (u == -1) {
return -1;
}
visited[u] = true; // 把u加入集合S中.
sum += d[u];
// 更新这个新加入的点能达到的距离
for (int v = 0; v < n; v++) {
// v未访问过,新加入的节点能使d[v]变小
if (visited[v] == false && G[u][v] < d[v]) {
d[v] = G[u][v];
}
}
return sum;
}
}