Kyopro Library
 
読み取り中…
検索中…
一致する文字列を見つけられません
dsu_rollback.hpp
[詳解]
1#pragma once
2#include"../../kyopro_library/template.hpp"
3
4/// @brief ロールバック可能DSU
5struct DsuRollback {
6 DsuRollback()=default;
7
8 /// @brief コンストラクタ
9 DsuRollback(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 int find(int x) {
17 if(par[x]==x) return x;
18 return find(par[x]);
19 }
20
21 /// @brief 頂点 x と y を連結し、true を返す
22 /// @brief 既に連結されている場合は false を返す
23 bool merge(int x, int y) {
24 x=find(x); y=find(y);
25 if(x==y) {
26 history.push_back({x,-1,-1,-1});
27 return false;
28 }
29 if(sz[x]<sz[y]) swap(x,y);
30 history.push_back({x,y,sz[x],sz[y]});
31 par[y]=x; sz[x]+=sz[y];
32 forest_count--;
33 return true;
34 }
35
36 /// @brief 最後に行った連結操作を取り消す
37 void undo() {
38 if(history.empty()) return;
39 auto[x,y,szx,szy]=history.back();
40 history.pop_back();
41 if(y==-1)return;
42 par[y]=y; sz[x]=szx; sz[y]=szy;
43 }
44
45 /// @brief DSUの状態を上書き保存する
46 void snapshot() { history.clear(); }
47
48 /// @brief 最後に snapshot した時点まで巻き戻す
49 void rollback() { while(!history.empty()) undo(); }
50
51 /// @brief 頂点 x を含む連結成分のサイズを返す
52 int size(int x) { return sz[find(x)]; }
53
54 /// @brief 頂点 x と y が同じ連結成分に属するか否かを返す
55 bool same(int x, int y) { return find(x)==find(y); }
56
57 /// @brief 連結成分の個数を返す
58 int count() { return forest_count; }
59
60 /// @brief 各頂点を連結成分に分解する
62 int n=par.size();
63 vector<vector<int>> ret(n);
64 for(int i=0; i<n; i++) ret[find(i)].push_back(i);
65 ret.erase(remove_if(ret.begin(),ret.end(),[&](const vector<int>& v) { return v.empty(); }),ret.end());
66 return ret;
67 }
68
69private:
70 vector<int> par,sz;
71 vector<tuple<int,int,int,int>> history;
72 int forest_count;
73};
ロールバック可能DSU
bool merge(int x, int y)
頂点 x と y を連結し、true を返す
DsuRollback()=default
void undo()
最後に行った連結操作を取り消す
vector< vector< int > > groups()
各頂点を連結成分に分解する
void rollback()
最後に snapshot した時点まで巻き戻す
bool same(int x, int y)
頂点 x と y が同じ連結成分に属するか否かを返す
void snapshot()
DSUの状態を上書き保存する
int find(int x)
頂点 x を含む連結成分の代表元を返す
DsuRollback(int n)
コンストラクタ
int count()
連結成分の個数を返す
int size(int x)
頂点 x を含む連結成分のサイズを返す