並查集判斷圖的連通
判斷圖的連通性判斷方法比較多,最常見的就是並查集、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的迷宮城