无向图的最小生成树之Kruskal算法

时间:2021-09-06 11:39:56
N个点M条边的无向连通图,每条边有一个权值,求该图的最小生成树。 Input第1行:2个数N,M中间用空格分隔,N为点的数量,M为边的数量。(2 <= N <= 1000, 1 <= M <= 50000) 
第2 - M + 1行:每行3个数S E W,分别表示M条边的2个顶点及权值。(1 <= S, E <= N,1 <= W <= 10000)Output输出最小生成树的所有边的权值之和。Sample Input
9 141 2 4
2 3 8
3 4 7
4 5 9
5 6 10
6 7 2
7 8 1
8 9 7
2 8 11
3 9 2
7 9 6
3 6 4
4 6 14
1 8 8
Sample Output
37

#include<bits/stdc++.h>using namespace std;#define maxn 50005#define INF 0x3f3f3f3fint par[maxn],rank[maxn];struct edge//边的信息 {	int u,v,cost;}es[maxn];bool cmp(edge a,edge b){	return a.cost<b.cost;}int init(int n)//初始化 {	for(int i=0;i<n;i++)	{		par[i]=i;		rank[i]=1;	}}int find(int x)//查询节点函数 {	if(par[x]==x)	{		return x;	}	else	{		return par[x]=find(par[x]);	}}void unite(int x,int y)//连接函数 {	x=find(x);	y=find(y);	if(x==y) return ;	if(rank[x]<rank[y])	{		par[x]=y;	}	else	{		par[y]=x;		if(rank[x]==rank[y]);		{			rank[x]++;		}	}}bool same(int x,int y)//判断是否 在同一个连通分量里面 {	return find(x)==find(y);}int main(){	int n,m,res=0;	scanf("%d %d",&n,&m);	for(int i=0;i<m;i++)	{		scanf("%d %d %d",&es[i].u,&es[i].v,&es[i].cost);	}	sort(es,es+m,cmp);//按照权值排序 	init(n);//初始化 	for(int i=0;i<m;i++)	{		edge e=es[i];		if(!same(e.u,e.v))		{			unite(e.u,e.v);			res+=e.cost;		}	}	printf("%d\n",res);	return 0;}