图的最小生成树

最小生成树:一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。目前用Kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出。

先说以下Kruskal算法:要让n个顶点的图连通,那么至少需要n-1条边,如果一个连通无向图不包含回路,那么就是一棵树,图的最小生成树就是让边的总长度之和最短,我们首先肯定从最小的开始选,依次按照边的顺序选择,直到用了n-1条边将整个图连通为止,即最小生成树。


Krustral算法代码如下:


#include <iostream>

using namespace std;

//边类
template<class DataType>
class Border
{
public:
	DataType u;   //第一个顶点
	DataType v;   //第二个顶点
	DataType w;  //边的权值
};

//算法核心类
template<class DataType>
class AirthmeticCure
{
public:
	Border<DataType> *edgeObject;  //边类对象数组
	AirthmeticCure(int m, int n)
	{
		this->edgeObject = new Border<DataType>[n];
		this->f = new int[m];
		for (int i = 1; i <= m; i++)  //并查集初始化
			f[i] = i;
	}
	void quickSort(int first, int last)
	{
		int i, j;
		Border<DataType> t;
		if (first > last)
			return;
		i = first;
		j = last;
		while (i != j)
		{
			while (edgeObject[j].w >= edgeObject[first].w && i < j)
				j--;
			while (edgeObject[i].w <= edgeObject[first].w && i < j)
				i++;
			if (i < j)
			{
				t = edgeObject[i];
				edgeObject[i] = edgeObject[j];
				edgeObject[j] = t;
			}
		}
		t = edgeObject[first];
		edgeObject[first] = edgeObject[i];
		edgeObject[i] = t;
		quickSort(first, i - 1);
		quickSort(i + 1, last);
		return;
	}

	int findAncestor(int v)
	{
		if (f[v] == v)
			return v;
		else
		{
			f[v] = findAncestor(f[v]);
			return f[v];
		}
	}


	bool merge(int u, int v)
	{
		int t1, t2;
		t1 = findAncestor(u);
		t2 = findAncestor(v);
		if (t1 != t2)  //判读两个点是否在同一个集合中
		{
			f[t2] = t1;
			return true;
		}
		return false;
	}
private:
	int *f;  //并查集
};

int main()
{
	int m, n, count = 0;
	int sum = 0;  //最小生成树的权值和
	cout << "请输入顶点个数和边的个数:";
	cin >> m >> n;
	AirthmeticCure<int> *Q = new AirthmeticCure<int>(m, n);
	for (int i = 1; i <= n; i++)
	{
		cin >> Q->edgeObject[i].u >> Q->edgeObject[i].v >> Q->edgeObject[i].w;
	}
	Q->quickSort(1, n);
	for (int i = 1; i <= n; i++)
	{
		if (Q->merge(Q->edgeObject[i].u, Q->edgeObject[i].v))
		{
			count++;
			sum = sum + Q->edgeObject[i].w;
		}
		if (count == m - 1)
			break;
	}
	cout << sum << endl;
	getchar();
	getchar();
	return 0;
}





运行结果如下:

 
 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值