最小生成樹|Kruskal算法

最小生成樹[模板]

題目描述
如題,給出一個無向圖,求出最小生成樹,如果該圖不連通,則輸出 orz。

輸入格式
第一行包含兩個整數N,MN,M表示該圖共有NN個結點和MM條無向邊。

接下來MM行每行包含三個整數Xi,Yi,ZiX_i,Y_i,Z_i,表示有一條長度爲ZiZ_i的無向邊連接結點Xi,YiX_i,Y_i

輸出格式

如果該圖連通,則輸出一個整數表示最小生成樹的各邊的長度之和。如果該圖不連通則輸出orz。

輸入輸出樣例

輸入
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
輸出
7

數據規模

對於100%100\%% 的數據:1N50001\le N\le 50001M2×1051\le M\le 2\times 10^5

KruskalKruskal算法

首先,最小生成樹就是在一個有NN個點的連通圖中取NN-11條邊,使得這NN-11條邊的權值和最小
而求最小生成樹有兩種算法:KruskalKruskalPrimPrim算法,而我們這裏先講KruskalKruskal
KruskalKruskal其實很容易理解,就是不斷的選取最小邊,前提是這條邊的兩個點之前是未連通的,這樣我們就很輕鬆的用並查集做就行了

代碼展示

KruskalKruskal的代碼十分簡單,34行代碼十分清爽

#include<bits/stdc++.h>
using namespace std;
struct node
{
	int x,y,val;
}a[200010];
int n,m,ans;
int f[5010];
bool Cmp(node x,node y)
{
	return x.val<y.val;
}
int find(int x)
{
	return f[x]==x?x:f[x]=find(f[x]);
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
		scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].val);
	sort(a+1,a+m+1,Cmp);
	for(int i=1;i<=n;i++)f[i]=i;
	for(int i=1;i<=m;i++)
	{
		if(find(a[i].x)!=find(a[i].y))
		{
			ans+=a[i].val;
			f[f[a[i].x]]=f[a[i].y];
		}
	}
	printf("%d\n",ans);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章