最小生成树讲解

写给自己看而已
有两种算法(关于这两个算法的名字没必要纠结。。。中文翻译出来叫啥都有)
1.普里姆算法(时间复杂度n2(n为点的数量))
思路:随便找一个点A,找到这个点A连接其他点B的最小的边(现在默认已经连上两个点了),将这两个点作为一个点A来看(跟其他点C连接的举例取两个点跟点C的最小值,一个for循环可实现)。
for循环处理所有的点,直到所有点连接上我们就能找到最小生成树
2.克鲁斯卡算法(时间复杂度n*logn (n为边的数量))
思路:先对所有边进行排序,取一个最小的边,连接最小的边的两个点,在取一个第二小的边,连接第二小的边上的两个点(注意不要形成环,否则就不是树了)
这两种算法的时间复杂度一个是针对边来计算一个是针对点来计算所以具体情况具体分析
附克鲁斯卡算法代码

#include<iostream>

using namespace std;
struct Edge 
{
	int nStart;
	int nEnd;
	int nValue;
};
void MySort(Edge *ArrEdge,int nLeft,int nRight)
{
	if (nLeft >= nRight)
	{
		return;
	}
	int i = nLeft;
	int j = nRight;
	int nTemp_Value = ArrEdge[nLeft].nValue;
	int nTemp_Start = ArrEdge[nLeft].nStart;
	int nTemp_End = ArrEdge[nLeft].nEnd;
	while (i < j)
	{
		while (i < j && ArrEdge[j].nValue >= nTemp_Value)
		{
			j--;
		}
		if (i < j)
		{
			ArrEdge[i].nValue = ArrEdge[j].nValue;
			ArrEdge[i].nStart = ArrEdge[j].nStart;
			ArrEdge[i++].nEnd = ArrEdge[j].nEnd;
		}
		while (i < j && ArrEdge[j].nValue <= nTemp_Value)
		{
			i++;
		}
		if (i < j)
		{
			ArrEdge[j].nValue = ArrEdge[i].nValue;
			ArrEdge[j].nStart = ArrEdge[j].nStart;
			ArrEdge[j--].nEnd = ArrEdge[j].nEnd;
		}
	}
	ArrEdge[i].nValue = nTemp_Value;
	ArrEdge[i].nStart = nTemp_Start;
	ArrEdge[i].nEnd = nTemp_End;
	MySort(ArrEdge,nLeft,i);
	MySort(ArrEdge, i + 1, nRight);
}
int FindParent(int *Parent, int nStart)
{
	while (nStart != Parent[nStart])
	{
		nStart = Parent[nStart];
	}
	return nStart;
}
int main()
{
	int n, m;//n为点的个数,m为边的个数
	
	while (cin >> n >> m)
	{
		Edge *vArrEdge = new Edge[m];
		int *Parent = new int[n];
		bool bFlag = false;
		int nAns = 0;
		int nEdgeCount = 0;
		for (int i = 0; i < m; i++)
		{
			int nTemp_Start,nTemp_End,nTemp_Value;
			cin >> vArrEdge[i].nStart >> vArrEdge[i].nEnd >> vArrEdge[i].nValue;
			vArrEdge[i].nStart--;
			vArrEdge[i].nEnd--;
		}
		MySort(vArrEdge, 0, m-1);
		for (int i = 0; i < n; i++)
		{
			Parent[i] = i;
		}
		
		for (int i = 0; i < m; i++)
		{
			int nTemp_Start = FindParent(Parent, vArrEdge[i].nStart);
			int nTemp_End = FindParent(Parent, vArrEdge[i].nEnd);
			if (nTemp_Start != nTemp_End)
			{
				Parent[nTemp_Start] = nTemp_End;
				nAns += vArrEdge[i].nValue;
				nEdgeCount++;
			}
			if (nEdgeCount == n - 1)
			{
				bFlag = true;
				break;
			}
		}
		if (bFlag)
		{
			cout << nAns << endl;
		}
		else
		{
			cout << "-1" << endl;
		}
		delete[] vArrEdge;
		delete[] Parent;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值