關於 C++ 並查集,你該瞭解這些

並查集,在一些有N個元素的集合應用問題中,我們通常是在開始時讓每個元素構成一個單元素的集合,然後按一定順序將屬於同一組的元素所在的集合合併,其間要反覆查找一個元素在哪個集合中。這一類問題近幾年來反覆出現在信息學的國際國內賽題中,其特點是看似並不複雜,但數據量極大,若用正常的數據結構來描述的話,往往在空間上過大,計算機無法承受;即使在空間上勉強通過,運行的時間複雜度也極高,根本就不可能在比賽規定的運行時間(1~3秒)內計算出試題需要的結果,只能用並查集來描述。(摘自百度

並查集其實就是找到自己的老大,形成各自的幫派↓
在這裏插入圖片描述
那我們先定義f[i]表示第 i 個人的老大是誰

int Find(int x){
    if(f[x] == x) return x;//像歐陽鋒和韋小寶一樣,自己做自己的老大[表情]
    return Find(f[x]);
}

然後是路徑壓縮:這時,因爲我們要路過他所有的上級,我們也可以順便使途中經過的人的大哥也變成老大。

inline int Find(int x){
	return x == f[x] ? x : (f[x] = find(f[x]));
//	if (x == f[x]) return x;
//	return f[x] = Find(f[x]);
}

路徑壓縮的代碼,看得懂很好,看不懂可以自己手動模擬一下,其實敲很簡單的。

大概的意思↓
在這裏插入圖片描述

模板題目👈點這

#include<bits/stdc++.h>
#define re register
using namespace std;

const int N = 1000000 + 1;
int f[N];

inline int Find(int x){
	return x == f[x] ? x : (f[x] = find(f[x]));
//	if (x == f[x]) return x;
//	return f[x] = Find(f[x]);
}

inline void unit(int x, int y){
	x = Find(x);
	y = Find(y);
	if (x != y) f[x] = y;		
}

int n , m;

signed main(){
	scanf("%d%d", &n, &m);
	for(re int i = 1;i <= n; i++) f[i] = i;
	for(re int i = 1;i <= m; i++){
		int x, y, z;
		scanf("%d", &z);
		if(z == 1){
			scanf("%d%d", &x, &y);
			unit(x, y);
		}
		else if(z == 2){
			scanf("%d%d", &x, &y);
			if(Find(x) == Find(y)) printf("Y\n");
			else printf("N\n");
		}
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章