【模板】最小生成树-Kruskal

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40727946/article/details/86515816

两种写法

第一种:使用数组

/*
时间复杂度:O(nlogn) 
*/
#include<bits/stdc++.h>
using namespace std;
#define MAX 200000+10
int n,m;	//n:结点的数量  m:边的数量 
int u[MAX],v[MAX],w[MAX],r[MAX],p[MAX];	//u[i]v[i]第i条边的两端点,w[i]第i条边的权值,r[i]第i小的边的序号,p[i]并查集 
int cmp(const int i, const int j) { return w[i] < w[j]; } 		//间接排序函数
int find(int x) { return p[x] == x ? x : p[x] = find(p[x]); }	//并查集的find
int Kruskal() 
{
	int ans = 0;
	for (int i = 0; i <= n; i++) p[i] = i; 	//初始化并查集
	for (int i = 0; i <= m; i++) r[i] = i; 	//初始化边序号
	sort(r, r + m, cmp); 	//给边排序
	for (int i = 0; i < m; i++) 
	{
		int e = r[i]; 		//找出当前边两个端点所在集合编号
		int x = find(u[e]); 
		int y = find(v[e]);
		if (x != y) 		//如果在不同集合,合并
		{ 
			ans += w[e]; 
			p[x] = y; 
		} 
	}
	return ans;
}
int main()
{
	cin>>n>>m;
	for(int i=0;i<m;i++)
	{
		cin>>u[i]>>v[i]>>w[i]; 
	}
	cout<<Kruskal()<<endl;
	return 0;
}
/*
洛谷 p3366 
输入:
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出:
7 
*/

第二种:使用结构体

/*
时间复杂度:O(nlogn) 
*/
#include<bits/stdc++.h>
using namespace std;
#define Max 200000+10
struct Edge
{
	int v,w,cost;
};
Edge a[Max];
int n,m,ans=0,p[Max];
bool cmp(Edge x,Edge y)
{
	return x.cost<y.cost;
}
int find(int x)
{
	return x==p[x]?x:p[x]=find(p[x]);
}
void Kruskal()
{
	for(int i=0;i<=n;i++)	p[i]=i;	//初始化并查集 
	sort(a,a+m,cmp);				//按照边的大小排序 
	int k=0,z=0;					//k为已经选择的边数,z为当前选择的边 
	ans=0;
	while(k!=n-1)			//选择出n-1条边,即为最小生成树 
	{
		int x=find(a[z].v);
		int y=find(a[z].w);
		if(x!=y)
		{
			p[x]=y;			//合并并查集 
			ans+=a[z].cost;
			k++;
		}
		z++;
	} 
}
int main()
{
	
	cin>>n>>m;
	for(int i=0;i<m;i++)
	{
		cin>>a[i].v>>a[i].w>>a[i].cost;
	}
	Kruskal();
	cout<<ans<<endl;
	return 0;
} 
/*
洛谷 p3366 
输入:
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出:
7 
*/

猜你喜欢

转载自blog.csdn.net/qq_40727946/article/details/86515816