用c++ 编写一个程序,实现求解带权连通图中最小生成树的算法。 具体要求:如果利用普里姆算法输出图中从顶点0出发的一棵最小生成树;如果利用克鲁斯卡尔算法,输出最小生成树的所有边。
时间: 2023-07-22 18:07:23 浏览: 111
最小生成树之普里姆prim算法C++实现
以下是使用C++实现Prim算法和Kruskal算法求解带权连通图的最小生成树的程序:
```c++
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 1001;
const int INF = 0x3f3f3f3f;
struct Edge{
int u, v, w;
}edge[MAXN*MAXN/2];
int n, m; // n为节点数,m为边数
int G[MAXN][MAXN]; // 邻接矩阵存图
int d[MAXN], vis[MAXN]; // d数组记录节点到生成树的最短距离,vis数组记录节点是否已加入生成树
int pre[MAXN]; // 记录每个节点在生成树中的前驱节点
// Prim算法
void Prim(int s){
memset(d, INF, sizeof(d)); // 初始化d数组
memset(vis, 0, sizeof(vis)); // 初始化vis数组
d[s] = 0; // 节点s到生成树的最短距离为0
for(int i=0; i<n; i++){
int u = -1; // u表示当前离生成树最近的节点
for(int j=0; j<n; j++){
if(!vis[j] && (u==-1 || d[j]<d[u])){
u = j;
}
}
vis[u] = true;
for(int v=0; v<n; v++){
if(!vis[v] && d[v]>G[u][v]){
d[v] = G[u][v];
pre[v] = u;
}
}
}
}
// Kruskal算法
int fa[MAXN]; // 并查集数组
bool cmp(Edge a, Edge b){
return a.w < b.w;
}
int find(int x){
if(fa[x] == x) return x;
return fa[x] = find(fa[x]);
}
void Kruskal(){
sort(edge, edge+m, cmp); // 将边按权值从小到大排序
for(int i=0; i<n; i++) fa[i] = i; // 初始化并查集数组
for(int i=0; i<m; i++){
int u = edge[i].u, v = edge[i].v, w = edge[i].w;
int x = find(u), y = find(v);
if(x != y){ // 如果不在同一个集合中,则加入生成树
pre[v] = u;
fa[x] = y;
}
}
}
int main(){
cin >> n >> m; // 输入节点数和边数
memset(G, INF, sizeof(G)); // 初始化邻接矩阵为INF
for(int i=0; i<m; i++){
int u, v, w;
cin >> u >> v >> w;
G[u][v] = G[v][u] = w; // 无向图
edge[i].u = u;
edge[i].v = v;
edge[i].w = w;
}
// Prim算法求解最小生成树
Prim(0);
cout << "Prim Algorithm:\n";
for(int i=1; i<n; i++){
cout << pre[i] << " -> " << i << " : " << d[i] << "\n";
}
// Kruskal算法求解最小生成树
Kruskal();
cout << "Kruskal Algorithm:\n";
for(int i=1; i<n; i++){
cout << pre[i] << " -> " << i << " : " << G[pre[i]][i] << "\n";
}
return 0;
}
```
程序中的Prim算法和Kruskal算法都使用了前驱节点数组pre来记录生成树的构造过程,输出最小生成树的边时只需按照pre数组输出即可。
阅读全文