#include <iostream>
#include<climits>
#include<vector>
#include<windows.h>
#define inf 0x3fffffff
using namespace std;
int n;
int prim(int &v0, vector< vector<int> >&adj);
void init_graph(vector< vector<int> >&adj);
int main()
{
	int begin;
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cout << "please input the number of vertex:";
	cin >> n;
	vector< vector<int> >A(n, vector<int>(n));
	init_graph(A);
	cout << "please input begin vertex:";
	cin >> begin;
	cout << "The weight of minimum tree is " << prim(begin, A) << endl;
	system("pause");
	return 0;
}

void init_graph(vector< vector<int> >&adj)//对于对称矩阵可优化为只输入上三角和对角线元素
{
	cout << "please input " << n << "-order adjacent matrix.\n";
	for (int i = 0; i<n; ++i)
	for (int j = 0; j<n; ++j)
		cin >> adj[i][j];
}

int prim(int &v0, vector< vector<int> >&adj)//时间复杂度为O(n^2)
{
	vector<bool>reach(n);
	for (auto &x : reach)
		x = false;
	reach[v0] = true;
	vector<int>mini;
	for (int i = 0; i<n; ++i)
	mini.push_back(adj[v0][i]);
	int mintree = 0;
	for (int j = 0; j<n; ++j)
	{
		int temp = v0, m = inf;
		for (int t = 0; t<n; ++t)
		if (!reach[t] && m>mini[t])//寻找未加入集合的节点所能构造的最小权值边
		{
			m = adj[v0][t];
			temp = t;
		}
		if (m == inf) break;/*如果找不到可构造的最小权值边,提前结束循环,得到最终的最小生成树, 
         可能并没有遍历所有节点*/
		mintree += m;
		reach[temp] = true;//将节点temp加入已遍历集合
		for (int s = 0; s<n; ++s)
		if (!reach[s] && adj[temp][s]<mini[s]) mini[s] = adj[temp][s];
        /*在已遍历的集合内,新加入的节点temp去更新权值库mini*/
	}
	return mintree;
}

代码测试结果如https://blog.csdn.net/weixin_43871369/article/details/88565694(同样的测试数据)

C++最小生成树Prim算法

总结:Kruskal VS Prim(https://www.cnblogs.com/JoshuaMK/p/prim_kruskal.html

方法上:Kruskal在所有边中不断寻找最小的边,Prim在U和V两个集合之间寻找权值最小的连接,共同点是构造过程都不能形成环。

时间上:Prim适合稠密图,复杂度为O(n * n),因此通常使用邻接矩阵储存,复杂度为O(e * loge),而Kruskal多用邻接表,稠密图 Prim > Kruskal,稀疏图 Kruskal > Prim。

空间上: Prim适合点少边多,Kruskal适合边多点少。

相关文章:

  • 2021-09-08
  • 2021-10-01
  • 2021-09-21
猜你喜欢
  • 2022-12-23
  • 2021-12-22
  • 2021-08-27
  • 2021-09-19
  • 2022-02-03
  • 2022-02-10
相关资源
相似解决方案