Kyopro Library
 
読み取り中…
検索中…
一致する文字列を見つけられません
dsu.hpp
[詳解]
1#pragma once
2#include"../../kyopro_library/template.hpp"
3
4/// @brief Disjoint Set Union
5struct DSU {
6 DSU()=default;
7
8 /// @brief コンストラクタ
9 DSU(int n) {
10 par.resize(n); iota(par.begin(),par.end(),0);
11 sz=vector<int>(n,1);
12 forest_count=n;
13 }
14
15 /// @brief 頂点 x を含む連結成分の代表元を返す
16 /// @note O(α(N))
17 int find(int x) {
18 if(par[x]==x) return x;
19 return par[x]=find(par[x]);
20 }
21
22 /// @brief 頂点 x と y を連結し、true を返す
23 /// @brief 既に連結されている場合は false を返す
24 /// @note O(α(N))
25 bool merge(int x, int y) {
26 x=find(x); y=find(y);
27 if(x==y) return false;
28 if(sz[x]<sz[y]) swap(x,y);
29 par[y]=x; sz[x]+=sz[y];
30 forest_count--;
31 return true;
32 }
33
34 /// @brief 頂点 x を含む連結成分のサイズを返す
35 /// @note O(α(N))
36 int size(int x) { return sz[find(x)]; }
37
38 /// @brief 頂点 x と y が同じ連結成分に属するか否かを返す
39 /// @note O(α(N))
40 bool same(int x, int y) { return find(x)==find(y); }
41
42 /// @brief 連結成分の個数を返す
43 /// @note O(1)
44 int count() { return forest_count; }
45
46 /// @brief 各頂点を連結成分に分解する
47 /// @note O(N)
49 int n=par.size();
50 vector<vector<int>> ret(n);
51 for(int i=0; i<n; i++) ret[find(i)].push_back(i);
52 ret.erase(remove_if(ret.begin(),ret.end(),[&](const vector<int>& v) { return v.empty(); }),ret.end());
53 return ret;
54 }
55
56private:
57 vector<int> par,sz;
58 int forest_count;
59};
Disjoint Set Union
Definition dsu.hpp:5
vector< vector< int > > groups()
各頂点を連結成分に分解する
Definition dsu.hpp:48
int count()
連結成分の個数を返す
Definition dsu.hpp:44
DSU()=default
int find(int x)
頂点 x を含む連結成分の代表元を返す
Definition dsu.hpp:17
bool merge(int x, int y)
頂点 x と y を連結し、true を返す
Definition dsu.hpp:25
DSU(int n)
コンストラクタ
Definition dsu.hpp:9
bool same(int x, int y)
頂点 x と y が同じ連結成分に属するか否かを返す
Definition dsu.hpp:40
int size(int x)
頂点 x を含む連結成分のサイズを返す
Definition dsu.hpp:36