ACM-資料結構-並查集
ACM競賽中,並查集(DisjointSets)這個資料結構經常使用。顧名思義,並查集即表示集合,並且支援快速查詢、合併操作。
並查集如何表示一個集合?它藉助樹的思想,將一個集合看成一棵有根樹。那又如何表示一棵樹?初始狀態下,一個元素即一棵樹,根即是元素本身。
並查集如何支援合併操作?不難發現,按照樹的思想,在同一棵樹中的所有元素,根都是相同的。也就是說,合併兩個不同的集合,只需要將其中一個集合的根設定為另一個集合的根即可,而需要改變根的那個集合,其實只需要改變根節點的父節點即可。
並查集如何支援快速查詢操作?如果完全按照上面的合併方法進行合併操作,最後生成的樹,可能是完全線性的,那麼查詢的時間複雜度就退化成了O(n),因為在這種情況下,程式不得不遍歷完所有節點才能查詢到當前元素所屬的根節點。
路徑壓縮演算法優化並查集查詢操作。按照集合原來的定義,集合中的元素是滿足無序性的,因此可以在查詢操作進行的過程中,當程式遍歷到根節點然後返回的時候,將所有屬於當前根節點的元素的父節點直接設定為當前根節點。如此一來,原來的一條鏈就變成了一般的樹了。當下一次查詢的時候,就可以很快的遍歷到根節點了,複雜度下降為O(1)。
還有一種優化查詢速度的方法,那就是合併兩個集合的時候,按秩進行合併,這裡的秩代表的以當前元素為根節點的元素個數。很明顯,將秩較小的樹合併到秩較大的樹上更優。
最後,就是具體如何用程式碼實現並查集?其實,並查集中只涉及到了儲存當前元素的父節點這一資訊,所以利用一個數組set[i]代表節點i的父節點即可,如果set[i]=i那麼代表當前集合的根即為i元素本身。
以一道例題為例,HDOJ:1212,時空轉移(點選開啟連結):
How Many Tables
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 17478 Accepted Submission(s): 8574
Problem Description Today is Ignatius' birthday. He invites a lot of friends. Now it's dinner time. Ignatius wants to know how many tables he needs at least. You have to notice that not all the friends know each other, and all the friends do not want to stay with strangers.
One important rule for this problem is that if I tell you A knows B, and B knows C, that means A, B, C know each other, so they can stay in one table.
For example: If I tell you A knows B, B knows C, and D knows E, so A, B, C can stay in one table, and D, E have to stay in the other one. So Ignatius needs 2 tables at least.
Input The input starts with an integer T(1<=T<=25) which indicate the number of test cases. Then T test cases follow. Each test case starts with two integers N and M(1<=N,M<=1000). N indicates the number of friends, the friends are marked from 1 to N. Then M lines follow. Each line consists of two integers A and B(A!=B), that means friend A and friend B know each other. There will be a blank line between two cases.
Output For each test case, just output how many tables Ignatius needs at least. Do NOT print any blanks.
Sample Input 2 5 3 1 2 2 3 4 5 5 1 2 5
Sample Output 2 4
Author Ignatius.L
Source
Recommend Eddy | We have carefully selected several similar problems for you:
給出一些人之間關係,如果兩個人有直接或間接關係,那麼這兩個人就屬於同一個集合,最後統計集合的個數。
分析:
並查集思想,初始每一個人屬於各自一個集合,如果當前讀入的兩個有關係的人不在同一集合,那麼就合併他們所屬的集合,集合個數減一。
原始碼:
#include <cstdio>
const int NumSets = 1005;
typedef int DisjSet[NumSets + 1];
typedef int Rank[NumSets + 1];
DisjSet S;
Rank R;
// Initialize the set and rank
void Initialize()
{
for(int i=0; i<NumSets; ++i)
{
S[i] = i;
R[i] = 1;
}
}
// Find father of the value, with the function of path compression
int Find(int value)
{
if(S[value] != value) S[value] = Find(S[value]);
return S[value];
}
// Union the value1 and value2 by the rank of the set which them local in
void SetUnion(int value1, int value2)
{
int fa1 = Find(value1);
int fa2 = Find(value2);
if(fa1 == fa2) return ;
if(R[fa1] >= R[fa2])
{
S[fa2] = fa1;
R[fa1] += R[fa2];
}
else
{
S[fa1] = fa2;
R[fa2] += R[fa1];
}
}
int main()
{//freopen("sample.txt", "r", stdin);
int cas;
scanf("%d", &cas);
while(cas--)
{
int n, m;
Initialize();
scanf("%d%d", &n, &m);
for(int i=0; i<m; ++i)
{
int a, b;
scanf("%d%d", &a, &b);
if(Find(a) != Find(b))
{
SetUnion(a, b);
--n;
}
}
printf("%d\n", n);
}
return 0;
}
其它並查集題目還有,HDOJ:1232、1558、1811、1829、1198。UESTC:203、1070。
相關推薦
ACM-資料結構-並查集
ACM競賽中,並查集(DisjointSets)這個資料結構經常使用。顧名思義,並查集即表示集合,並且支援快速查詢、合併操作。 並查集如何表示一個集合?它藉助樹的思想,將一個集合看成一棵有根樹。那又如何表示一棵樹?初始狀態下,一個元素即一棵樹,根即是元素本身。 並查集如何
【資料結構並查集】POJ1988——線樹上的帶權並查集
問題描述: 給定30000個方塊,一開始每個方塊各自一摞,每次有兩種操作的方法,一種是將含有編號xx的一摞放在含有編號yy的一摞上,另一種是統計編號xx的方塊下有幾個方塊,每次將第二種操作的結果
資料結構-並查集
並查集 一種特殊的樹, 由子節點執行父節點 方便解決連線問題 主要操作 union(p,q) 用於合併p, q所在的集合 isConnected(p,q) 判斷p,q是否相連 程式碼實現 首先先定義並查集的介面, 介面定義如下: package tr
資料結構——並查集Union Find
一、並查集解決了什麼問題? 1、網路中節點間的連線狀態:這裡的網路是一個抽象的概念,指的是使用者之間形成的網路 2、兩個或兩個以上集合之間的交集 二、對並查集的設計 對於一組資料,主要支援兩個操作 public interface UnionFind {
資料結構——並查集
等價關係:滿足自反,對稱,傳遞。 等價類:指相互等價的元素的最大集合。一個元素只能屬於一個等價類。 離線等價類問題中,已知n和R,確定所有的等價類。 線上等價類問題中,初始時有n個元素,每個元素都屬於一個獨立的等價類。 find(element)返回所屬的等價類。union
資料結構----並查集Java
並查集:(union-find sets)是一種簡單的用途廣泛的集合. 並查集是若干個不相交集合,能夠實現較快的合併和判斷元素所在集合的操作,應用很多。 應用場景: 網路連線判斷: 如果每個pair中的兩個整數分別代表一個網路節點,那麼該pair就是
POJ 1182 食物鏈 [資料結構-並查集 union-find sets]
在輸入時可以先判斷題目所說的條件2和3,即: 1>若(x>n||y>n):即當前的話中x或y比n大,則假話數目num加1. 2>若(x==2&&x==y):即當前的話表示x吃x,則假話數目num加1. 而不屬於這兩種情況外的話語要利用
資料結構--並查集的原理及實現
一,並查集的介紹 並查集(Union/Find)從名字可以看出,主要涉及兩種基本操作:合併和查詢。這說明,初始時並查集中的元素是不相交的,經過一系列的基本操作(Union),最終合併成一個大的集合。 而在某次合併之後,有一種合理的需求:某兩個元素是否已經處在同一個集合中了?因此就需要Find操作。 並
2019.9.17 初級資料結構——並查集及其應用
一、並查集基礎 (一)引入 我們先來看一個問題。 某學校有N個學生,形成M個俱樂部。每個俱樂部裡的學生有著一定相似的興趣愛好,形成一個朋友圈。一個學生可以同時屬於若干個不同的俱樂部。根據“我的朋友的朋友也是我的朋友”這個推論可以得出,如果A和B是朋友,且B和C是朋友,則A和C也是
數據結構 並查集
一個 efault mar left pts turn 一個數 baseline 數組 並查集是一種數據結構,字面意思上來說,就是一個支持合並和查詢的集合。 並查集 並查集的建立 1 void init() 2 { 3 for (int i = 1; i <
NOI2018歸程(Kruskal重構樹)(以及騙分數據結構並查集)
沒有 這一 目標 div 相對 之前 大寫字母 top color 題目描述 本題的故事發生在魔力之都,在這裏我們將為你介紹一些必要的設定。 魔力之都可以抽象成一個 n 個節點、m 條邊的無向連通圖(節點的編號從 1 至 n)。 我們依次用 l,a 描述一條邊的長度、海拔
數據結構——並查集
技術 bool 數組 用戶 span pen main 就是 set 並查集,是我目前為止見過的,實現起來最淳樸的數據結構,但是功能也很強大。 並查集核心由三個數組和兩個函數構成。 數組pre[ ]記錄了每個點的前導點是什麽,數組data[ ]記錄數據,數組size[
noip提高組資料結構模板[並查集,st表,樹狀陣列,線段樹]
/*資料結構*/ //並查集 for(int i=1;i<=n;i++) fa[i]=i;*** int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} //st表 for(int i=2;i<=n;i++) Log[i]=Lo
資料結構學習筆記------並查集(附cf例題)
並查集是將原始的資料集S看成一個森林,每棵樹代表一個集合。初始時,每個資料看成一顆只有根節點的樹,根據具體要求,將若干樹合併起來組成若干個含有節點較多的樹,每棵樹就是一個集合。此資料結構可以方便的對資料集S進行:(1)查詢其屬於哪個集合(2)將一個集合合併到另一個集合的操作。要注意的是,
[學習筆記]可持久化資料結構 可持久化並查集
可持久化:支援查詢歷史版本和在歷史版本上修改 可持久化陣列 主席樹做即可。 【模板】可持久化陣列(可持久化線段樹/平衡樹) 可持久化並查集 可持久化並查集 主席樹做即可。 要按秩合併。(路徑壓縮每次建logn條鏈,會卡爆空間MLE) 主席樹節點,維護father
資料結構09—— 並查集(Union-Find)
一、關於並查集 並查集(Union-Find)是一種樹型的資料結構,常用於處理一些不相交集合(Disjoint Sets)的合併及查詢問題。並查集(Union-Find)從名字可以看出,主要它涉及兩種基本操作:合併和查詢。這說明,初始時並查集中的元素是不相交的,經過一系列的基本操作(Union)
資料結構實現 9.1:並查集_陣列結構實現(C++版)
資料結構實現 9.1:並查集_陣列結構實現(C++版) 1. 概念及基本框架 2. 基本操作程式實現 2.1 聯合操作 2.2 查詢操作 2.3 其他操作 3. 演算法複雜度分析 3.1 聯合操作
資料結構實現 9.2:並查集_樹思想實現(C++版)
資料結構實現 9.2:並查集_樹思想實現(C++版) 1. 概念及基本框架 2. 基本操作程式實現 2.1 聯合操作 2.2 查詢操作 2.3 其他操作 3. 演算法複雜度分析 3.1 聯合操作
(Java資料結構和演算法)最小生成樹---Kruskal演算法(並查集)
該文章利用prime演算法求得連通圖的最小生成樹對應的邊權最小和,prime演算法是從頂點的角度思考和解決問題。本文介紹的Kruskal演算法將從邊的角度考慮並解決問題,利用了並查集方便地解決了最小生成樹的問題。 本文參考博文 //並查集 class UnionSameSet{
基礎演算法與資料結構(三)普通並查集
簡介 在平時的計算中,常常會遇到集合劃分的問題,例如一個集合S={a1,a2,a3,a4},按照一定規則我們可以劃分為S1={a1,a2},S2={a3},s3={a4}。但是在劃分好集合後,又該如何快速確認任意兩個元素之間的關係呢。由此引出並查集。 並查集簡介 並查集最關鍵的表現就是一個集合中的每