重学数据结构系列之——图论算法之Prim算法

学习来源:计蒜客

1.首先了解一些概念:

生成树:一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。(简单来说就是顶点不变,但边数是n-1条,而且抽取出来后,图还是连通的)
最小生成树:如何从一个带权图中抽出一棵生成树,使得边权值和最小,这棵生成树就叫做最小生成树。(就是找生成树中权值之和最小的)


2.Prim算法


即普里姆算法,简单来说就是从一个点出发,每次取出了生成树中的边以外最小的边

Prim 算法一般应用于边较为稠密的图,也就是顶点较少、而边较多的图。


3.代码实现

#include <iostream>
#include <cstring>
#include <vector>
#include <queue>

using namespace std;
//定义一个大整数,下面表示距离很远就对了
const int INF = 0x3f3f3f3f;

//一个边的结构
struct Edge {
	//vertex:一条边的另一个端点
	//weight:该边权重
	int vertex, weight;
};

class Graph{
private:
	int n;
	bool *visited;
	vector<Edge> *edges; //邻接表
public:
	//dist(distance)://用于保存某个顶点到生成树的距离
	int *dist;
	Graph(int input_n){
		n = input_n;
		edges = new vector<Edge>[n];
		dist = new int[n];
		memset(visited, 0, n * sizeof(bool));
		//初始化每个dist为0x3f3f3f3f,这是个大整数,表示距离很远
		memset(dist,0x3f, n * sizeof(int));
	}
	~Graph(){
		delete[] dist;
		delete[] visited;
		delete[] edges;
	}
	void insert(int x, int y, int weight) {
		Edge edge1,edge2;  
<span style="white-space:pre">		</span>edge1.vertex = x;  
<span style="white-space:pre">		</span>edge1.weight = weight;  
<span style="white-space:pre">		</span>edge2.vertex = y;  
<span style="white-space:pre">		</span>edge2.weight = weight;  
<span style="white-space:pre">		</span>edges[x].push_back(edge2);  
<span style="white-space:pre">		</span>edges[y].push_back(edge1);
	}

	//v:起点
	int prim(int v){
		//定义并初始化总权值为0
		int total_weight = 0;
		//起点距离起点的距离为0
		dist[v] = 0;
		for (int i = 0; i < n; i++) {//外层循环是要找到n个顶点
			int min_dist = INF, min_vertex; //初始化最小距离为一个大的整数,min_vertex为最小距离的那个点的编号
			//从n个点中找最近的顶点(离生成树最近的),i=0时,当然是起点自己离自己(暂时生成树只有起点)最近啦,而且我们初始化其距离为0了,下一个循环是更新这个点连着的边 另外一个端点的距离为其边的权值
			for (int j = 0; j < n; j++) {
				//若没访问过,且距离小于最小距离
				if (!visited[j] && dist[j] < min_dist) {
					//更新最小距离
					min_dist = dist[j];
					//保存最小的顶点的编号
					min_vertex = j;
				}
			}
			//加上最小距离(权值)
			total_weight += min_dist;
			//设置为已访问
			visited[min_vertex] = 1;
			//枚举这个结点的所有的边
			for(Edge &j : edges[min_vertex]){
				//如果边的另一个端点没访问过且权值小于距离
				if(!visited[j.vertex] && j.weight < dist[j.vertex]){
					//就更新其距离为边的权值
					dist[j.vertex] = j.weight;
				}
			}
		}
		return total_weight;
	}
};

int main() {
	int n, m;
	cin >> n >> m;
	Graph g(n);
	for (int i = 0; i < m; i++) {
		int a, b, c;
		cin >> a >> b >> c;
		g.insert(a, b, c);
	}
	cout << g.prim(0) << endl;
	return 0;
}



运行环境:

C++11

输入按照下图输入




posted @ 2016-04-16 22:11  SEC.VIP_网络安全服务  阅读(174)  评论(0编辑  收藏  举报