时间:o(n2) 空间:o(n)
集合避圈法,解决连通各个单位,费用最少的问题。
选取一点加入S集合中,一次选取V-S离S集合最近的点,加入S中,知道V-S为空集,最小生成树完成。
使用优先队列优化
#include<iostream>
#include<queue>
using namespace std;
const int maxnum = 100;
const int inf = 0x3f3f3f3f;
typedef struct graph {
int vexs[maxnum][maxnum];
int vexnums;
int edgenums;
}G; //带权邻接矩阵
typedef struct edge {
int u;
int v;
int w;
edge(int ui, int vi, int wi)
{
u = ui;
v = vi;
w = wi;
}
edge()
{
}
//运算符重载
friend bool operator >(const edge e1,const edge e2)
{
return e1.w > e2.w;
}
}edge;
G g;
bool s[maxnum];
//构建邻接矩阵
void creategraph() {
cout << "输入顶点数量和边数量:" << endl;
cin >> g.vexnums >> g.edgenums;
cout << "输入对应的边关系:" << endl;
for (int i = 1; i <= g.vexnums; i++)
{
for (int j = 1; j <= g.vexnums; j++)
{
g.vexs[i][j] = inf;
}
}
for (int i = 0; i < g.edgenums; i++)
{
int a, b, w;
cin >> a >> b >> w;
g.vexs[a][b] = w;
g.vexs[b][a] = w;
}
}
void prim(int u)
{
int wpl = 0;
s[u] = true; //将u顶点加入s集合中
priority_queue<edge,vector<edge>,greater<edge> > queue; //边队列
edge* path = new edge[g.vexnums - 1]; //最小生成树结果
int k = 0;
//将u顶点的邻接边都加入队列中
for (int i = 1; i <= g.vexnums; i++)
{
queue.push(edge(u, i, g.vexs[u][i]));
}
for (int i = 1;; i++)
{
//求出v-s内最近顶点
edge e = queue.top();
int t = e.v;
queue.pop();
cout << e.u << "-->" << e.v << "-->" << e.w <<"-->"<<s[t]<<endl;
if (e.w==inf||k==g.vexnums-1) break;
if (s[t]) continue;
s[t] = true; //把顶点加入S中
path[k++] = e;
wpl += e.w;
//更新queue将改变的边重新加入队列中
for (int i = 1; i <= g.vexnums; i++)
{
if (!s[i])
{
queue.push(edge(t, i, g.vexs[t][i])); //t->i
}
}
}
cout << "WPL:" << wpl << endl;
cout << "最小生成树路径为:" << endl;
for (int i = 0; i < k; i++)
{
cout << "<" << path[i].u << "," << path[i].v << "> ";
}
cout << endl;
}
int main()
{
creategraph();
int u;
cin >> u;
prim(u);
return 0;
}
测试数据
7 12
1 2 23
1 6 28
1 7 36
2 3 20
2 7 1
3 7 4
3 4 15
4 7 9
4 5 3
5 7 16
5 6 17
6 7 25
1