Prime算法解决的也是最小生成树的问题,思路很直观,开始时,任意选择一个点作为根,
然后选择离这个点最近的一个点和它连通,组成一个新的连通分量,再用新选的点更新其他未
被选择的点到已知连通分量的距离,更新完毕之后,选择一个离已知连通分量最近的点和已知
连通分量连通,组成新的连通分量,重复这个过程。直到所有点都被选中。
Prime算法和Dijstra算法很像,不同点在于Prime更新的是从已知连通分量到其他各个
顶点的距离,Dijstra更新的是从源点到其他各个顶点的距离。
//表示边
struct Edge {
int u;//起点
int v;//终点
int w;//权重
};
class Prime {
vector<int> dis;
vector<bool> book;
public:
int minimumSpanningTreeSum(vector<Edge> &edges,int n) {
if (edges.empty()) {
return {};
}
book.resize(n, false);
dis.resize(n,INT_MAX);
vector<vector<int>> G(n,vector<int>(n));
//初始化
for(int i = 0;i < n;i++) {
for(int j = 0;j < n;j++) {
if(i == j) {
G[i][j] = 0;
}
else {
G[i][j] = INT_MAX;
}
}
}
//把边读入二维数组,方便后续访问
for(int i = 0;i < edges.size();i++) {
G[edges[i].u][edges[i].v] = edges[i].w;
G[edges[i].v][edges[i].u] = edges[i].w;
}
//初始化dis数组,选取第一条的第一个顶点
for(int i = 0;i < n;i++) {
dis[i] = G[edges[0].u][i];
}
//选择第一个点
book[edges[0].u] = true;
int count = 1;
int ans = 0;
while (count < n) {
int min = INT_MAX;
int minV = -1;
for(int i = 0;i < n;i++) {
if(book[i] == false && dis[i] < min) {
min = dis[i];
minV = i;
}
}
if (minV == -1) {
//没找到,结束
continue;
}
book[minV] = true;
count++;
ans += dis[minV];
for(int k = 0;k < n;k++) {
if(book[k] == false && dis[k] > G[minV][k]) {
dis[k] = G[minV][k];
}
}
}
return ans;
}
};