最小生成树

图算法之最小生成树

1.      对于一个无向连通图G=(V,E),若存在一个无回路的子集TE,它连接了所有的顶点,切其权值之和:

2.      Kruskal算法

伪代码如下:

MST_KRUSKAL(G,w)
	A = {}
	for vertex in V
		do make-set(v)
	sort the edges based on weight
	for edge(u,v) in E taken by nonincreasing order by weight
		do if find_set(u) != find_set(v)
			then A = A U {(u,v)}
				union(u,v)
	return A
 

大致思想是先将边按权值排序,按顺序取边,如果该边的两个节点不处于同一集合,说明该边未加入到子集中,则将边加入子集,将两个节点并入同一集合中。

3.      Prim算法

Prime算法的思想是将图中端点分为两个集合,集合A中的是已访问过的节点,集合B中是仍未访问的节点,每次寻找能将两个集合连接起来的权值最小的边,伪代码如下

MST_PRIM(G,w,r)   //r表示起始节点
for each u in V
	do key[u] = INF
		parent[u] = NIL
key[r] = 0
Q = V
while Q!={}
	do u = extract_min(Q)
		for v in Adj[u]
			do if v in Q and w(u,v)<key[v]
				then parent[v] = u
					key[v] = w(u,v)
4.   C++代码
Kruskal算法	
#include <iostream>
#include <vector>
#include <map>
#include <fstream>
using namespace std;

#define maxn 1000

int nodes,edges;
int father[maxn];
int graph[maxn][maxn];
int weight[maxn][maxn];
bool visited[maxn];
multimap<int,pair<int,int>> weight_edge;  //以边的权重为键,边的两个点为值。
vector<pair<int,int>> result;

void make_set(int i)  
{
	father[i] = i;
}
int find_set(int i)
{
	return father[i];

}
void _union(int i,int j)
{
	int temp = father[j];
	for(int m =1;m<=nodes;m++)   //遍历所有节点,将父节点为father[j]的节点的父节点更新为father[i],即归为同一个集合
		if(father[m] == temp)
			father[m] = father[i];
}
void mst_kruskal()
{
	for(int i=1;i<=nodes;i++)
		make_set(i);
	multimap<int,pair<int,int>>::iterator map_it = weight_edge.begin();
	while(map_it !=weight_edge.end())
	{
		int _first,_second;
		_first = map_it->second.first;
		_second = map_it->second.second;
		if(find_set(_first) != find_set(_second)) //不在一个集合中
		{
			result.push_back(make_pair(_first,_second));
			_union(_first,_second);
			map_it++;
		}
		else
			map_it++;
	}
}

int main()
{
	ifstream graph_data;
	graph_data.open("graph.txt");
	
	graph_data>>nodes>>edges;
	for(int i=0;i<edges;i++)
	{
		int first,second,temp_weight;
		graph_data>>first>>second>>temp_weight;

		graph[first][second] = 1;
		graph[second][first] = 1;       //无向图

		weight[first][second] = temp_weight;
		weight[second][first] = temp_weight;

		weight_edge.insert(make_pair(temp_weight,make_pair(first,second)));   //插入map中
	}
	memset(visited,false,sizeof(visited));
	mst_kruskal();
	for(int i=0;i<result.size();i++)
	{
		int m,n;
		m = result[i].first;
		n = result[i].second;

		cout<<m<<"->"<<n<<" "<<weight[m][n]<<endl;
	}
	return 0;
}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值