最小生成树——Prim算法
1.最小生成树的概念
2.Prim算法
(1)算法本质:
有一个图G,求它的最小生成树,
定义两个集合,U表示所有已经加入当前最小生成树的点,
U - V 表示 U 以外的点,也就是没有加入当前最小生成树的点。
定义三个数组,closest[i] 表示 i 节点(不在 U 里)距离 U 最近的那个点的编号(必须是直接连接),
lowclosest[i] 表示 i 节点 与 closest[i] 点之间的那条边的权值。
s[i] 表示 i 是否在 U 集合内
(2)算法步骤:
1.初始化。令集合 U = {1}, 1 ∈ V, 并初始化数组 closest[], lowclosest[] 和 s[];
2.在集合 U - V 中找 lowclosest 值最小的点 t, 并将节点 t 加入集合 U 中。这里注意一个难点:如果 t 是初始化的点,说明图不连通,需要特判
3.如果集合 U 为空,则算法结束
4.对集合 V - U 中的点,或者是可以说在 t 所连接的点中所有属于 U - V 的点更新 closest[] 值 和 lowclosest[] 值
重复以上步骤,最终得到的是一个权值和最小的生成树
(3)算法实现
void Prim() {
for (int i = 1; i < n; i++) {
int temp = i;
int t = 1;
for (int j = 1; j <= n; j++) {
if (!s[j] && lowclosest[j] < temp) { //属于 U - V 集合且可以更新最小值
temp = lowclosest[j];
t = j;
}
}
if (t == 1) { //图不连通
return 0;
}
s[t] = true; //标记是在 U 集合里
for (int j = 1; j <= n; j++) {
if (!s[j] && c[t][j] < lowclosest[j]) {
lowsest[i] = c[t][j];
closest[j] = t;
}
}
}
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += closest[i];
}
}
(4)算法复杂度:
时间:O(n * n)
空间:O(n)