Prim算法
用途
处理最小生成树(MST)问题,即在给定的图中求树,使得这棵树拥有图中所有顶点,且所有边都是图中已知的边,且满足整棵树的边权之和最小。适用于边多的稠密图。
算法描述
与Dijkstra算法思想相似:
- 创建并维护树结点集合S, 以及结点到集合S的最短距离数组d;
- 每次循环遍历图中所有未访问结点,将离集合S最近的结点u并入集合,并累加边权;
- 以结点u为集合S的新接入点,更新剩余未访问结点到集合S的最短距离d[i];
- 重复上述步骤,直到将所有结点都纳入集合S中。
代码实现
const int maxn = 1000;
const int INF = 1000000000;
int g[maxn][maxn], n; // 邻接矩阵,结点个数
int d[maxn]; // 记录到树的最短距离
bool visit[maxn] = {false}; // 判断是否已加入树集合
int Prim(int s)
{
int sum = 0; // 记录边权和
for (int i = 0; i < n; i++) // 初始化
d[i] = INF;
d[s] = 0; // 根结点到树距离为0
for (int i = 0; i < n; i++)
{
int u = -1, minD = INF;
for (int j = 0; j < n; j++) // 寻找到树最近的结点未访问结点
{
if (visit[j] == false && d[j] < minD)
{
minD = d[j];
u = j;
}
}
if (u == -1) // 循环过程中若未找到最近未访问结点,说明图不是单一连通块
return -1; // 无法生成树,返回-1
visit[u] = true; // 加入树集合
sum += d[u]; // 累加边权
for (int v = 0; v < n; v++)
{
if (visit[v] == false && g[u][v] < INF && g[u][v] < d[v]) // 以u为新接入点更新未访问结点到树的最短距离
d[v] = g[u][v];
}
}
return sum;
}