题意:
本题要求你用Prime算法求图的最小生成树。
本题的图都是无向图且最小生成树不存在二义性(包括每一步选入的节点)。
请你输出节点选择的次序和邻接矩阵
思路:
对于记录数据。用邻接矩阵arr记录无向图,用lowCost向量记录v个顶点的最低权重,用visit向量记录顶点是否归入最小树。因为我们先将0号顶点作为最小树的根,所以将其余点与0顶点的权重值作为lowCost的初始值。
对于循环次数。因为已经将0顶点最为最小树的根,所以我们只需再做v-1次循环,每次循环将一个顶点归入最小树,最后刚好v个顶点入树。
对于每一次循环。取lowCost中权重最小的点k,将其归入最小树,且visit[k]=true。然后更新记录最小树矩阵和lowCost即可。
对于更新lowCost向量。因为我们选择了k点入最小树,lowCost可能会受其余点与k点权重值的影响,所以我们将lowCost中的数值、其余点与k点的权重值二者进行比较取较小值。
源码:
#include<iostream>
#include<vector>
const int INF = 1 << 30;
using namespace std;
int main() {
int v = 0, e = 0;
cin >> v >> e; //输入顶点及边
vector<int>lowCost(v); //权重最低数组
vector<bool>visit(v); //是否归入树内
vector<vector<int>> arr(v); //记录图
vector<vector<int>> ans(v); //记录最小树
for (int i = 0; i < v; i++) {
arr[i].resize(v, INF);
ans[i].resize(v);
}
for (int i = 0; i < e; i++) { //计入邻接矩阵
int x = 0, y = 0;
cin >> x >> y;
cin >> arr[x][y];
arr[y][x] = arr[x][y]; //无向图
}
//初始化权重最低数组,因为先将0号顶点作为根,所以将其余点与0顶点的权重值作为lowCost的初始值
for (int i = 0; i < v; i++)
lowCost[i] = arr[0][i];
lowCost[0] = 0; //将0号顶点作为根
visit[0] = true; //0号顶点以归入树
//因为已将0顶点归入树,所以再做v-1次循环,每次归入一个顶点,最后刚好v个顶点入树
for (int i = 1; i < v; i++) {
int min = INF, k = 0; //定义权重最小值及其顶点
for (int j = 0; j < v; j++) { //取权重数组中权重最小的值及其顶点
if (!visit[j] && min > lowCost[j]) {
min = lowCost[j];
k = j;
}
}
cout << k << " ";
visit[k] = true;
for (int i = 0; i < v; i++) { //更新最小树。将取到的权重最小的点计入邻接矩阵
if (lowCost[k] == arr[i][k]) {
ans[i][k] = arr[i][k];
ans[k][i] = arr[i][k];
}
}
//更新lowCost数组。将其余点的权重最小值、其余点与刚取到的权重最小点的权重比较,取最小值
for (int j = 0; j < v; j++) {
if (!visit[j] && lowCost[j] > arr[k][j])
lowCost[j] = arr[k][j];
}
}
cout << endl;
for (int i = 0; i < v; i++) { //输出最小树
for (int j = 0; j < v; j++) {
cout << ans[i][j] << " ";
}
cout << endl;
}
return 0;
ps:用INF = 1 << 30(无穷大)作为矩阵的初始值。巧妙地用lowCost向量来选择要入树的点。