/*
《数据结构》严蔚敏版
P173、174 普里姆算法 最小生成树 图7.16
U-未选点集合 S-已选点集合
初始 S = {源点}
每次从 未选点集合中选出与已选点有关联边且权值最小的点
加入到已选点中 直到 S = V (V为点的全集)
//测试数据 地图
1000000 6 1 5 1000000 1000000
6 1000000 5 1000000 3 1000000
1 5 1000000 5 6 4
5 1000000 5 1000000 1000000 2
1000000 3 6 1000000 1000000 6
1000000 1000000 4 2 6 1000000
*/
#include <iostream>
#include <cstdio>
#include <memory.h>
#include <vector>
using namespace std;
const int MAXN = 100;
const int MAX = 1000000;//假设1000000表示无穷大
struct Node {
int v1,v2;
};
int map[MAXN][MAXN];//地图
vector<Node> save_e;//保存结果
vector<int> S;//保存已选点
int U[MAXN];//未选点
int n = 6;
int cost = MAX;
int v1,v2,cur_v;
void min_tree(int source) {//最小生成树
S.push_back(source);
memset(U,0,sizeof(U));
U[source] = 1;
while (S.size() < n) {
for (int i = 0; i < S.size(); i++) {//遍历所有与已选点相关联的边
cur_v = S[i];
for (int j = 1; j <= n; j++) {
if (!U[j] && map[cur_v][j] < MAX && map[cur_v][j] < cost) {
//找出未选点中与S集合点中有关联边且权值最小的点
cost = map[cur_v][j];//保存最小权值
v1 = cur_v;//保存此时S集中与选出的未选点相关联的点 即“前驱”
v2 = j;//保存选出的点 “后继”
}
}
}
S.push_back(v2);//将选出的点加入到集合S
U[v2] = 1;//标志该点已选
cost = MAX;//恢复cost 为无穷大 用于选取下一点
Node temp;
temp.v1 = v1; temp.v2 = v2;//保存此时选出的边
save_e.push_back(temp);
}
}
int main() {
for (int i = 1; i <= n; i++) {//输入地图
for (int j = 1; j <= n; j++)
scanf("%d",&map[i][j]);
}
min_tree(1);//调用算法
cout << "该图最小生成树依次选出的边为:" << endl;
for (int i = 0; i < save_e.size(); i++) { //输出结果 依次选出的边 集合
Node temp = save_e[i];
cout << temp.v1 << " " << temp.v2 << endl;
}
return 0;
}