您的位置:首页 > 理论基础 > 数据结构算法

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

2016-04-16 22:10 411 查看

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>
;
dist = new int
;
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

输入按照下图输入









内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: