代码如下:
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 210
#define MAXM 1010
using namespace std;
class Edge { //边
public:
int start, end, value;
Edge() {
start = -1;
end = -1;
value = 0;
}
void setEdge(int s, int e, int v) {
start = s;
end = e;
value = v;
}
friend bool cmpEdge(Edge a, Edge b); //比较函数,供sort使用
};
bool cmpEdge(Edge a, Edge b) { //升序排列
return a.value < b.value;
}
class Graph {
private:
int map[MAXN][MAXN];
Edge e[MAXM];
int n, m;
public:
void inputGraph() { //输入数据
int a, b, x;
cin >> n >> m;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
map[i][j] = 0;
}
}
for (int i = 0; i < m; i++) {
cin >> a >> b >> x;
map[a][b] = x;
map[b][a] = x;
e[i].setEdge(a, b, x);
}
}
/*
判断图的连通性,这里使用dfs
*/
int mark[MAXN];
void dfs_visit(int u = 0) {
mark[u] = 1;
for (int i = 0; i < n; i++) {
if (map[u][i] != 0 && mark[i] == 0) {
dfs_visit(i);
}
}
}
bool isConnected() {
memset(mark, 0, sizeof(mark));
dfs_visit();
for (int i = 0; i < n; i++) {
if (mark[i] == 0) {
return false;
}
}
return true;
}
/*
构造最小生成树,这里使用Prim,并使用并查集判断连通块
*/
int f[MAXN];
int getFather(int x) { //寻找祖先节点+路径压缩
if (f[x] != x) {
f[x] = getFather(f[x]);
}
return f[x];
}
void prim() {
if (!isConnected()) {
cout << "不是连通图,无最小生成树" << endl;
return;
}
cout << "最小生成树如下:\n";
int a, b,tot=0;
for (int i = 0; i < n; i++) { //初始化并查集
f[i] = i;
}
sort(e, e + m, cmpEdge); //对边集按权值排序
for (int i = 0; i < m; i++) {
a = e[i].start;
b = e[i].end;
if (getFather(a) != getFather(b)) {
tot += e[i].value;
cout << a << " " << b << " " << e[i].value << endl; //将此边输出
f[getFather(a)] = getFather(b); //合并两个连通块
}
}
cout << "总长度" << tot << endl;
}
};
int main() {
while (1) {
Graph g;
g.inputGraph();
g.prim();
cout << "是否继续,y/n\n";
char ch;
cin >> ch;
if (ch != 'y') {
break;
}
}
}