1. 程式人生 > >並查集判斷圖的連通

並查集判斷圖的連通

判斷圖的連通性判斷方法比較多,最常見的就是並查集、DFS、BFS 這幾種,網上的程式碼也很多,文章最後也給出了一些參考,這裡主要講一講並查集。

因為有判斷有向圖中是否存在尤拉路徑的需求,需要先判斷有向圖的基圖是否連通,於是就找了一些演算法,有了這篇文章,文章偏向於個人的理解與想法,深入瞭解可以點解參考。

並查集由一個記錄節點的根節點的陣列(或者類似容器,字典)和兩個函式(find, join)構成。容器(陣列)記錄了每個點的根節點是哪個,函式 find 用於查詢某個節點的根節點,join 函式是合併兩個具有相連關係的節點。

先看程式碼:

pre = {}


def find(x):
    r = x
    while
pre[r] != r: r = pre[r] i = x while i != r: # 路徑壓縮,平衡樹層次的效果 j = pre[i] pre[i] = j i = j return r def join(x, y): fx = find(x) fy = find(y) if fx != fy: # root = min(fx, fy) # 平衡樹的層次的效果 # pre[fx] = root # pre[fy] = root
pre[fx] = fy def judge(n, edges): ''' 判斷是否連通 :param n: 節點數 :param edges: 邊的集合 :return: 是否連通 >>> judge(4, [(0, 1), (2, 0),(2, 3)]) True >>> judge(4, [(2, 0),(2, 3)]) False ''' for i in range(n): pre[i] = i for i in range(len(edges)): join(edges[i][0
], edges[i][1]) group = 0 for i in range(n): if pre[i] == i: group += 1 if group == 1: return True else: return False if __name__ == '__main__': import doctest doctest.testmod()

思路為:對於圖中的每個節點,設定它的根節點為它本身。對圖中的每一條邊的兩個端點進行合併操作,得到的結果就是相互連通的節點的根節點指向同一個節點。所以只要查詢一下結果中節點的根節點等於其本身的節點的數目就可以知道這個圖被分成連通的幾個部分,如果連通,則為 1。

pre 字典中儲存著每個節點的根節點,find 開始之前要初始化。find 函式經過一層層的尋找,最終找到 x 的根節點,返回。join 函式對邊的兩個端點所屬的集合做合併,如果兩個節點的根節點不同,則通過指定其中一個根節點作為另一個根節點的父節點,達到合併所屬集合的效果。

最終只需要判斷 pre 中本身為本身的父節點的頂點數目即可判斷連通性。路徑壓縮和父節點選擇是一種平衡整個關係樹的層次的方法,自己體會。

相關推薦

判斷連通

判斷圖的連通性判斷方法比較多,最常見的就是並查集、DFS、BFS 這幾種,網上的程式碼也很多,文章最後也給出了一些參考,這裡主要講一講並查集。 因為有判斷有向圖中是否存在尤拉路徑的需求,需要先判斷有向圖的基圖是否連通,於是就找了一些演算法,有了這篇文章,文章偏

-用判斷中是否有環(能夠應用到kruskal的最小生成樹)

     先不介紹並查集的概念,先從它的應用說起吧,它有兩個功能,第一就是判斷給定的一個節點是否屬於某一個集合,更確切的說是屬於哪個集合。第二個功能就是合併兩個集合。       給定一組資料,如:1, 2, 3, 4, 5, 6, 7, 8,  9,他們是一個大的集合,但

利用進行中兩頂點是否連通判斷

//利用並查集判斷無向圖中兩節點是否連通 #include <iostream> #include<cstdio> using namespace std; const int maxn=100+5; int vset[maxn]; int rank

【HDU 4514】【樹的直徑 dfs或者判斷環】【給定一個無向可能是非連通的,如果中存在環,就輸出YES,否則就輸出樹的直徑】

描述: 湫湫系列故事——設計風景線 Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 4610    Acc

hdu1272小希的迷宮(判斷回路和是否連通)

show set onclick spa 分享 return print 聯通 兩個 傳送門 迷宮中不能有回路,還要連通 如果最後集合數是一個那就是連通,否則不聯通 要合並的兩個頂點在相同集合內,表示出現了回路 輸入時註意一下 1 #include<

Head of a Gang(,多連通)

題目描述 One way that the police finds the head of a gang is to check people's phone calls. If there is a phone call between A and B, we say that

hdu 1272小希的迷宮(判斷無向迴路)

並查集~~~ 判斷圖是否連通且無迴路 待連線的兩點如果祖先節點相同,那麼就構成迴路 #include<stdio.h> #define max(a,b) a>b?a:b #define min(a,b) a<b?a:b int father[1000

逆向思維 + 用動態維護連通塊的個數——Luogu P1197題解

code space 題目 == 個數 sin getch 都是 delete 題目大意: 給你一個 $ n $ 個點的圖與 $ m $ 條邊,接下來給出一個長度為 $ k $ 個整數,按照給出整數的順序依次刪掉對應編號的點,求出一開始的連通塊的個數與接下來每次刪除一個點後

【hiho】14 無間道之論--

const lse string turn problem scan -c for sca 傳送門:無間道之並查集 分析 並查集的分析可以看上面的傳送門,寫的挺好的了。 其實在我看來並查集就是一種方便的維護集合的一種技巧,提出了代表元素這一概念。 My AC Code #i

UVA1160(判斷強聯通分量)

https://cn.vjudge.net/problem/UVA-1160 只要該化合物的兩個分量已經屬於屬於同一強連通分量,化合物就不穩定,直接拒絕 #include<iostream> #include<cstdio> #include<algorithm

HDU 1213 How Many Tables(求強連通分量)

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

hdu 1325Is It A Tree?(判斷有向樹)

Problem Description A tree is a well-known data structure that is either empty (null, void, nothing) or is a set of one or more nodes connected by d

hdu1232(求強連通

Problem Description 某省調查城鎮交通狀況,得到現有城鎮道路統計表,表中列出了每條道路直接連通的城鎮。省政府“暢通工程”的目標是使全省任何兩個城鎮間都可以實現交通(但不一定有直接的道路相連,只要互相間接通過道路可達即可)。問最少還需要建設多少條道路?   

小希的迷宮 HDU - 1272(判斷是否成環)

#include<stdio.h> #include<iostream> #include<algorithm> using namespace std; int fa[100005],vis[100005],flag;//flag判斷是否成環 int n , m

1272(判斷是否成環)

#include<stdio.h> #include<iostream> #include<algorithm> using namespace std; int fa[100005],vis[100005],flag;//flag判斷是否

HDU3081:Marriage Match II (Floyd/+二分匹配/最大流(+二分))

Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5469 &n

[loj#121][線段樹分治][]動態連通性

Description 動態加邊刪邊維護圖連通性 n<=5000,m<=500000 允許離線 題解 wori這種模板都不會寫了嗎… 預處理每條邊在什麼時候出現什麼時候消失 根據時間建線段樹 線段樹每個節點開一個vector存在他管理這段時間

poj 2513 歐拉回路+判斷是否聯通+Trie樹

http://poj.org/problem?id=2513 最初看到 第一感覺---map  一看250000的資料量 果斷放棄 然後記得以前看過,trie代替map,尤其當資料量特別大的時候 學到了: 1、Trie代替map的思想,可以在單詞結尾的tree[i][tk]

[bzoj1854][Scoi2010]遊戲(/二分最大匹配)

#include<cstdio> #include<algorithm> #include<cmath> #include<cstdlib> #i

杭電1272(+判斷是否存在環形區域)

小希的迷宮(難度:1) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Problem Description 上次Gardon的迷宮城