欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

c語言數據結構之并查集 總結

 更新時間:2018年08月11日 16:28:29   作者:Alger_jhun  
一種用于管理分組的數據結構。它具備兩個操作:(1)查詢元素a和元素b是否為同一組 (2) 將元素a和b合并為同一組,需要的朋友可以參考下

并查集(Union-Find Set):

一種用于管理分組的數據結構。它具備兩個操作:(1)查詢元素a和元素b是否為同一組 (2) 將元素a和b合并為同一組。

注意:并查集不能將在同一組的元素拆分為兩組。

并查集的實現:

用樹來實現。

使用樹形結構來表示以后,每一組都對應一棵樹,然而我們就可以將這個問題轉化為樹的問題了,我們看兩個元素是否為一組我們只要看這兩個元素的根是否一致。顯然,使用樹形結構將問題簡單化了。合并時是我們只需要將一組的根與另一組的根相連即可。

并查集的核心在于,一棵樹的所有節(jié)點根節(jié)點都為一個節(jié)點。使用Find函數查詢時,也是查詢到這個節(jié)點的根節(jié)點。

一行并查集:

int find(int x)
{
 return p[x]==x? x:find(p[x]); //x的父節(jié)點保存在p[x]中,如果沒有父節(jié)點則p[x]=x。
}

實現:

int node[i]; //每個節(jié)點 
 
//初始化n個節(jié)點 
void Init(int n){ 
 for(int i = 0; i < n; i++){ 
 node[i] = i; 
 } 
} 
//查找當前元素所在樹的根節(jié)點(代表元素) 
int find(int x){ 
 if(x == node[x]) 
 return x; 
 return find(node[x]); 
} 
//合并元素x, y所處的集合 
void Unite(int x, int y){ 
 //查找到x,y的根節(jié)點 
 x = find(x); 
 y = find(y); 
 if(x == y) 
 return ; 
 //將x的根節(jié)點與y的根節(jié)點相連 
 node[x] = y; 
} 
//判斷x,y是屬于同一個集合 
bool same(int x, int y){ 
 return find(x) == find(y)

并查集的路徑壓縮:

在特殊情況下,這棵樹是一條長長的樹鏈,設鏈的最后一個結點為x,則每次執(zhí)行find(x)都會遍歷整條鏈。效率十分的地下。 改進方法很簡單,只要把遍歷過的結點都改成根的子結點,后面的查詢就會變的快很多。

并查集的復雜度

加入這兩個優(yōu)化之后,并查集的效率就非常高。對n個元素的并查集操作一次的復雜度是: O(α(n))。這里,α(n)是阿克曼(Ackermann)函數的反函數。效率要高于O(log n)。

不過這里O(α(n))是平均復雜度。也就是說,多次操作之后平均復雜度為O(α(n)),換而言之,并不是每一次操作都滿足O(α(n))。

路徑壓縮后的優(yōu)化代碼:

 int node[i]; //每個節(jié)點 
 int rank[i]; //樹的高度 
 
 //初始化n個節(jié)點 
 void Init(int n){ 
 for(int i = 0; i < n; i++){ 
  node[i] = i; 
  rank[i] = 0; 
 } 
 } 
 //查找當前元素所在樹的根節(jié)點(代表元素) 
 int find(int x){ 
 if(x == node[x]) 
  return x; 
 return node[x] = find(node[x]); //在第一次查找時,將節(jié)點直連到根節(jié)點 
 } 
 //合并元素x, y所處的集合 
 void Unite(int x, int y){ 
 //查找到x,y的根節(jié)點 
 x = find(x); 
 y = find(y); 
 if(x == y) 
  return ; 
 //判斷兩棵樹的高度,然后在決定誰為子樹 
 if(rank[x] < rank[y]){ 
  node[x] = y; 
 }else{ 
  node[y] = x; 
  if(rank[x] == rank[y]) rank[x]++: 
 } 
 } 
 //判斷x,y是屬于同一個集合 
 bool same(int x, int y){ 
 return find(x) == find(y); 
 } 

實例分析:

題目:部落

在一個社區(qū)里,每個人都有自己的小圈子,還可能同時屬于很多不同的朋友圈。我們認為朋友的朋友都算在一個部落里,于是要請你統(tǒng)計一下,在一個給定社區(qū)中,到底有多少個互不相交的部落?并且檢查任意兩個人是否屬于同一個部落。

輸入格式:

輸入在第一行給出一個正整數N(<= 104),是已知小圈子的個數。隨后N行,每行按下列格式給出一個小圈子里的人:

K P[1] P[2] ... P[K]

其中K是小圈子里的人數,P[i](i=1, .., K)是小圈子里每個人的編號。這里所有人的編號從1開始連續(xù)編號,最大編號不會超過104。

之后一行給出一個非負整數Q(<= 104),是查詢次數。隨后Q行,每行給出一對被查詢的人的編號。

輸出格式:

首先在一行中輸出這個社區(qū)的總人數、以及互不相交的部落的個數。隨后對每一次查詢,如果他們屬于同一個部落,則在一行中輸出“Y”,否則輸出“N”。

輸入樣例:
4
3 10 1 2
2 3 4
4 1 5 7 8
3 9 6 4
2
10 5
3 7

輸出樣例:

10 2
Y
N

分析:典型并查集問題。

一個部落對應一個集合。 根節(jié)點數量等于部落數量。
并查集把每個部落的人連起來,記錄哪些人出現過,枚舉標號10000,找出有多少人和部落,查詢并查集維護。

源碼分析:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int pre[10005];
int f[10005];
 
void init() { //初始化父集合pre[10005],以及出現的標志數組f[10005]
	for(int i=0; i<10004; i++)
		pre[i]=i, f[i]=0;
}
 
int find(int x) { //并查集查找根節(jié)點的 遞歸程序
	return pre[x]==x? x : pre[x]=find(pre[x]);
}
 
int main()
{
	init();
	int n,q,k,a,b;
	cin>>n;
	for(int i=0; i<n; i++) {
		cin>>k>>a;
		f[a]=1;
		for(int j=1; j<k; j++) {
			cin>>b;
			f[b]=1;
			int x=find(a);
			int y=find(b);
			if(x!=y) pre[x]=y;
		}
	}
	int cnt=0,tot=0; //cnt為所有人數 tot為部落數量
	for(int i=0; i<10004; i++) {
		if(f[i] == 1) { //如果標志為1 則說明出現過,cnt加一
			cnt++;
			if(pre[i]==i) tot++; //如果下標為本身 說明其為根節(jié)點 根節(jié)點數量為部落的數量
		}
	}
	cout<<cnt<<" "<<tot<<endl;
	cin>>q;
	for(int i=0; i<q; i++) {
		cin>>a>>b;
		if(find(a) == find(b)) //若兩參數 有同一根節(jié)點 說明為一個部落。
			cout<<"Y"<<endl;
		else cout<<"N"<<endl;
	}
	return 0;
}

好了,這篇文章就介紹到這了。

相關文章

  • C++實現在文本中找出某個單詞的位置信息

    C++實現在文本中找出某個單詞的位置信息

    本文給大家分享的是使用C++實現在文本中找出某個單詞的位置信息,就是給出此單詞所在的行和列,有需要的小伙伴可以參考下。
    2016-02-02
  • C語言中時間的基本用法小結

    C語言中時間的基本用法小結

    處理時間是編程中經常遇到的問題,C語言中提供了一些時間處理函數,在此記錄下一些基本的用法。下面這篇文章主要給大家介紹了C語言中關于時間的基本用法的相關資料,需要的朋友可以參考借鑒,感興趣的朋友們來一起看看吧。
    2017-01-01
  • Qt?CEF融合技QCefView使用教程(推薦)

    Qt?CEF融合技QCefView使用教程(推薦)

    QCefView是一個與Chromium?Embedded?Framework集成的Qt第三方開源庫,LGPL許可,可以在項目中免費使用,功能類似CEF、QWebEngineView,提供C++和web交互的能力,本文給大家介紹Qt?CEF融合技QCefView使用教程,感興趣的朋友參考下吧
    2021-12-12
  • C++實現多項式相乘

    C++實現多項式相乘

    這篇文章主要介紹了C++實現多項式相乘方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • C++變量引用的概念介紹

    C++變量引用的概念介紹

    這篇文章主要介紹了C++變量引用的概念介紹,簡單提到了與指針概念的不同,通過代碼場景分析給大家介紹的非常詳細,需要的朋友可以參考下
    2021-08-08
  • Pipes實現LeetCode(192.單詞頻率)

    Pipes實現LeetCode(192.單詞頻率)

    這篇文章主要介紹了Pipes實現LeetCode(192.單詞頻率),本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下
    2021-08-08
  • C語言模擬實現通訊錄程序過程

    C語言模擬實現通訊錄程序過程

    這篇文章主要介紹了C語言模擬實現通訊錄程序過程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2023-02-02
  • Window10下安裝VS2022社區(qū)版的實現步驟(圖文教程)

    Window10下安裝VS2022社區(qū)版的實現步驟(圖文教程)

    很多和同學們在接觸c語言的時候都是使用VS,本文主要介紹了Window10下如何安裝VS2022社區(qū)版的實現步驟,具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • Visual Studio調試C/C++教程指南

    Visual Studio調試C/C++教程指南

    VisualStudio是微軟開發(fā)的一款集成開發(fā)環(huán)境軟件,本文主要介紹了Visual Studio調試C/C++教程指南,熟悉地掌握基于VS的C/C++調試技術,可以大幅提升調試性能,感興趣的可以了解一下
    2024-06-06
  • C++ LeetCode1780判斷數字是否可以表示成三的冪的和

    C++ LeetCode1780判斷數字是否可以表示成三的冪的和

    這篇文章主要為大家介紹了C++ LeetCode1780判斷數字是否可以表示成三的冪的和題解示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12

最新評論