朋友圈問題
並查集,顧名思義,主要功能是合併和查詢,主要處理一些集合的合併問題。假設有n
個元素,它們分別屬於一些集合,每個元素最多只能屬於乙個集合,每個集合都有乙個「祖先」,這些集合就構成乙個並查集。
並查集的表示方式很簡單,只需要乙個陣列v
(陣列的大小是元素的個數),對每個元素i
,v[i]
表示它的父節點或祖先節點(如果i
本身是某個集合的祖先節點,則v[i]==i
)。下圖的並查集包括4
個集合,v=[0,1,2,2,2,5,5,5,5,5]
。
進一步地,陣列counts
表示以每個元素為祖先的集合大小。以上圖為例,counts=[1,1,3,0,0,5,0,0,0,0]
。
通常初始化每個元素自成乙個集合,所有集合的大小都是1
。
class
unionfind
;
並查集主要有兩個方法:查詢和合併。
查詢並返回元素x
的祖先節點。
int unionfind::
find
(int x)
return anc;
}
如果某2
個元素不屬於同一集合,且需要合併它們,將小集合合併到大集合裡。
x
和y
是它們各自所屬集合的祖先節點。
void unionfind::
merge
(int x,
int y)
班上有n
名學生。其中有些人是朋友,有些則不是。他們的友誼具有是傳遞性。如果已知a
是b
的朋友,b
是c
的朋友,那麼我們可以認為a
也是c
的朋友。所謂的朋友圈,是指所有朋友的集合。
給定乙個n * n
的矩陣m
,表示班級中學生之間的朋友關係。如果m[i][j] = 1
,表示已知第i
個和j
個學生互為朋友關係,否則為不知道。你必須輸出所有學生中的已知的朋友圈總數。
使用並查集的思路:
(1)開始時每個學生自成乙個集合。
(2)遍歷矩陣m
,根據學生之間的關係及各自的祖先節點,判斷是否要合併集合(修改陣列v
和counts
)。由於矩陣m
是對稱的,所以只需遍歷一半。
(3)最後,通過陣列v
或counts
統計集合的數量。
class
unionfind
counts = vector<
int>
(n,1);
v = vector<
int>
(n);
for(
int i =
0; i < n;
++i)
for(
int i =
0; i < n;
++i)}}
}int ans =0;
for(
int i =
0; i < n;
++i)
}return ans;
}private
: vector<
int> v;
vector<
int> counts;
};
資料結構 並查集
並查集,顧名思義,合併 查詢 集合 並查集是一種樹型的資料結構,用於處理一些不相交集合 disjoint sets 的合併及查詢問題。常常在使用中以森林來表示。對於概念等等的這裡不再贅述,直接講解應用。應用1 判斷圖中有多少聯通分量 或者圖是否聯通 聯通分量 1 hdu 1213 應用2 判斷圖是否...
資料結構 並查集
time limit 1000ms memory limit 65536k 某城市有n個人,現在給定關於n個人的m條資訊,m條資訊是兩個人在同乙個小區,根據所給資訊,判斷這個城市最多可能有多少個小區。n個人編號為1 n。多組輸入。每組第一行有兩個整數n,m 2 n 50000,0 m n 2 接下來...
資料結構 並查集
一 基本概念 並查集是一種樹型的資料結構,用於處理一些不相交集合 disjoint sets 的合併及查詢問題。常常在使用中以森林來表示。集就是讓每個元素構成乙個單元素的集合,也就是按一定順序將屬於同一組的元素所在的集合合併。在一些有n個元素的集合應用問題中,通常是在開始時讓每個元素構成乙個單元素的...