最小生成树Prim算法

MST(Minimum Spanning Tree,最小生成树)
经典运用城市铺路问题
通常有最小生成树有PrimKruskal两种算法

这边先介绍Prim算法
时间复杂度是O(n^2)
牛客上有道选择题答案说是O(n+e)我是不太明白

Prim算法是从点的角度出发
所以两者相比较Prim算法适合于解决边稠密的网

具体流程
初始化
图中所有顶点集合为G
加入MST的点集合为V
任取一点a开始,加入V中
步骤
1) 找集合G - V中的点b,与V中某点a最小的权值
2) 将这点加入V中,b与a相连就构成一条边
3)返回到第一步,直到所有顶点都加入V中,就得到一颗MST

下面是模拟过程
在这里插入图片描述在这里插入图片描述
这里测试数据与上图无关
Sample Input
9 15
0 1 10
0 5 11
1 2 18
1 6 16
2 3 22
2 8 8
3 4 20
3 7 16
3 6 24
3 8 21
4 5 26
4 7 7
5 6 17
6 7 19
1 8 12
Sample Output
0 1
0 5
1 8
8 2
1 6
6 7
7 4
7 3

#include <cstdio>
#include <iostream>
#include <algorithm>

using namespace std;

const int MAXEDGE = 20;
const int MAXVEX = 20;
const int INIFINITY = 100000;

//封装顶点,边,数组顶点到顶点间的权值 
typedef struct{
	
	int arc[MAXVEX][MAXVEX];
	int numVertexes, numEdges;
	
}MGraph;

MGraph G;

void CreateMGraph(MGraph *G);

void MiniSpanTree_Prim(MGraph G);

int main(int argc, const char * argv[])
{

	CreateMGraph(&G);
	
	MiniSpanTree_Prim(G);

	return 0;
}

void CreateMGraph(MGraph *G)
{ 
	cin >> G->numVertexes >> G->numEdges;
	
	//初始化 
	for(int i = 0; i < G->numVertexes; i++)
		for(int j = 0; j < G->numVertexes; j++)
			//顶点自身到自身无权值,不连通的顶点间取无穷大 
			if(i == j)
				G->arc[i][j] == 0;
			else
				G->arc[i][j] = G->arc[j][i] = INIFINITY;
	
	//构造连通图 
	for(int i = 0; i < G->numEdges; i++)
	{
		int v1,v2,w;
		scanf("%d %d %d", &v1, &v2, &w);
		G->arc[v1][v2] = w;
	}
	
	//利用连通的对称性
	for(int i = 0; i < G->numVertexes; i++)
		for(int j = 0; j < G->numVertexes; j++)
			G->arc[j][i] = G->arc[i][j];
}

//Prim算法生成最小生成树 
void MiniSpanTree_Prim(MGraph G)
{	
	int adjvex[MAXVEX] = {0, };		//adjvex[i] 当下已生成的树中到i权值最小的顶点 
	int lowcost[MAXVEX] = {0, };	//lowcost[i] 对应i到adjvex[i]两顶点中的权值 
	
	lowcost[0] = 0;		//赋值为0表示已加入生成树中 
	
	for(int i = 1; i < G.numVertexes; i++){ 
		lowcost[i] = G.arc[0][i];		//0与各顶点的权值存入 
		adjvex[i] = 0;		//初始化目前全是与顶点0相接 
	}
	
	for(int i = 1; i < G.numVertexes; i++)
	{
		int min = INIFINITY;
		int k = 0;		//初始化最小值 
		
		//循环所有顶点,找出最小权值,把顶点赋给k 
		for(int j = 1; j < G.numVertexes; j++)
			if(lowcost[j] != 0 && lowcost[j] < min){
				min = lowcost[j]; 
				k = j;		
			}
		
		printf("%d %d\n", adjvex[k], k);
		lowcost[k] = 0;		//标记该顶点已完成任务 
		
		//重新寻找从刚加入的顶点到各顶点的权值是否比原先的adjvex[j]到j的权值更小 
		for(int j = 1; j < G.numVertexes; j++)
			if(lowcost[j] != 0 && G.arc[k][j] < lowcost[j]){
				adjvex[j] = k;
				lowcost[j] = G.arc[k][j];
			}
	}
}

650

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值