1. 程式人生 > >Kruscal&它的好朋友並查集

Kruscal&它的好朋友並查集

……我覺得我需要寫一下並查集……畢竟我這麼菜……不寫篇部落格過幾天我都不知道自己學過  找爸爸  並查集

但我這麼菜,我也寫不出太多東西……那就讓這倆一起吧QwQ 反正kruscal也要用並查集的QwQ

並查集

並查集,俗稱找爸爸(霧),就是多個集合之間的查詢&合併,具體操作包括:查詢某兩點是否在同一集合,合併某兩點所在集合,以及一些鬼畜的操作

先貼程式碼,再說思想

int find(int x)
{
	if (f[x]!=x)
		f[x]=find(f[x]);
	return f[x];
}

上面的是並查集最最最核心的操作:找爸爸 

其實原理非常的簡單:如果x不是自己的爸爸,那麼x一定不是根節點,於是我們再去找x的爸爸的爸爸,直到x的爸爸的爸爸的爸爸的……p終於是自己的爸爸了,於是x和他的爸爸們都找到了他們的爸爸,也都直接把他們的爸爸變成了p,這其實也就是路徑壓縮

找到了爸爸,接下來就是查詢操作

原理更簡單了,(程式碼我都不想放),分別查詢兩個節點的爸爸,看看這兩個點的爸爸是不是一個爸爸

最後就是合併操作了

更簡單了,把一個點的爸爸變成另一個點的爸爸的兒子

#include<bits/stdc++.h>
using namespace std;
int f[10010];
int fa(int x)
{
	if (f[x]==x)
		return x;
	return f[x]=fa(f[x]);
}
int main()
{
	int n,m;
	cin>>n>>m;
	for (int i=1;i<=n;i++)
		f[i]=i;
	for (int i=1;i<=m;i++)
	{
		int z,a,b;
		cin>>z>>a>>b;
		if (z==1)
			f[fa(a)]=fa(b);
		if (z==2)
			if (fa(a)==fa(b))
				cout<<"Y"<<endl;
			else
				cout<<"N"<<endl;
	}
 	return 0;
}

咳咳咳接下來是kruscal

Kruscal

一個簡陋的、沒什麼用的、目錄

  • 演算法思想
  • 直接上程式碼

演算法思想

從小到大遍歷每條邊,如果這條邊的兩個端點不在一個集合裡,就合併他們,直到所有點都被連起來

程式碼實現

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<algorithm>
#include<queue>
#include<cstdlib>
using namespace std;
int jishuqi,f1,f2,f[10100];
struct edge
{
	int a,b,val;
}e[10010];
int find(int x)
{
	if (f[x]!=x)
		f[x]=find(f[x]);
	return f[x];
}
bool cmp(edge a,edge b)
{
	return a.val<b.val;
}
int main()
{
	int n,m;
	cin>>n>>m;
	for (int i=1;i<=n;i++)
		f[i]=i;
	for (int i=1;i<=m;i++)
		cin>>e[i].a>>e[i].b>>e[i].val;
	sort(e+1,e+m+1,cmp);
	for (int i=1;i<=m;i++)
	{
		f1=find(e[i].a);
		f2=find(e[i].b);
		if (f1==f2)
			continue;
		else
		{
			f[f1]=f[f2];
			jishuqi=jishuqi+e[i].val;
		}	
	}
	cout<<jishuqi;
	return 0;
}

【完結撒花✿✿ヽ(°▽°)ノ✿】【這次好草率的說】 

【蒟蒻wyf要把學過的所有演算法都寫成部落格!】