This documentation is automatically generated by online-judge-tools/verification-helper
#include "Graph/dsu_02_max.hpp"
部分永続 Union Find の簡易版。
辺の追加順が昇順である必要がある。
頂点 $u$ と頂点 $v$ が連結になったときの辺の値を返すことができる。
ここらへんの問題殴る用のライブラリ。
関数名など | 機能 | 計算量 |
---|---|---|
Kruskal_dsu(int N) |
宣言。 $N$ 頂点 $0$ 辺のグラフを作成する。 辺の型 T を渡す。 |
$\text{O} (N)$ |
bool merge(int a, int b, T w) |
頂点 $a$ と頂点 $b$ を辺の大きさ $w$ で結ぶ。辺の追加に成功したらtrue 、既に連結である場合はfalse が返される。辺は昇順に追加する必要がある。 |
$\text{O} (\log N)$ |
bool same(int a, int b) |
頂点 $a$ と頂点 $b$ が連結であるかを返す。 | $\text{O} (\log N)$ |
int leader(int a) |
頂点 $a$ の属する連結成分の代表元を返す。 | $\text{O} (\log N)$ |
int size(void) |
現在の連結成分の数を返す。(int型であることに注意) | $\text{O} (1)$ |
int size(int a) |
頂点 $a$ の属する連結成分のサイズを返す. | $\text{O} (\log N)$ |
T max_edge(int u, int v) |
最小全域木上の頂点 $u$ から頂点 $v$ までの単純パスのうち最大辺を返す。 ・同一頂点の場合は 0 を返す。・非連結の場合は -1 を返す。 |
$\text{O} (\log N)$ |
std::vector<std::vector<int>> groups() |
グラフを連結成分に分けてその情報を返す. 返り値は「「一つの連結成分の頂点番号のリスト」のリスト」で, リスト内でどの順番で頂点が格納されているかは未定義である. | $\text{O} (N)$ |
template <class T> struct Kruskal_dsu {
public:
Kruskal_dsu() : _n(0) {}
Kruskal_dsu(int n) : _n(n), num_component(n), parent_or_size(n, -1),
dat(n, std::numeric_limits<T>::max()) {}
bool merge(int u, int v, T w) {
assert(0 <= u && u < _n);
assert(0 <= v && v < _n);
int x = leader(u), y = leader(v);
if (x == y) return false;
if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);
parent_or_size[x] += parent_or_size[y];
parent_or_size[y] = x;
dat[y] = w;
num_component--;
return true;
}
bool same(int u, int v) {
assert(0 <= u && u < _n);
assert(0 <= v && v < _n);
return leader(v) == leader(u);
}
int leader(int v) {
assert(0 <= v && v < _n);
while(parent_or_size[v] >= 0) v = parent_or_size[v];
return v;
}
int size() {
return num_component;
}
int size(int v) {
assert(0 <= v && v < _n);
return -parent_or_size[leader(v)];
}
T max_edge(int u, int v){
T ans = 0;
while(u != v){
if (dat[u] > dat[v]) std::swap(u, v);
ans = dat[u], u = parent_or_size[u];
if(u < 0) return -1;
}
return ans;
}
private:
int _n, num_component;
// root node: -1 * component size
// otherwise: parent
std::vector<int> parent_or_size;
std::vector<T> dat;
};
#line 1 "Graph/dsu_02_max.hpp"
template <class T> struct Kruskal_dsu {
public:
Kruskal_dsu() : _n(0) {}
Kruskal_dsu(int n) : _n(n), num_component(n), parent_or_size(n, -1),
dat(n, std::numeric_limits<T>::max()) {}
bool merge(int u, int v, T w) {
assert(0 <= u && u < _n);
assert(0 <= v && v < _n);
int x = leader(u), y = leader(v);
if (x == y) return false;
if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);
parent_or_size[x] += parent_or_size[y];
parent_or_size[y] = x;
dat[y] = w;
num_component--;
return true;
}
bool same(int u, int v) {
assert(0 <= u && u < _n);
assert(0 <= v && v < _n);
return leader(v) == leader(u);
}
int leader(int v) {
assert(0 <= v && v < _n);
while(parent_or_size[v] >= 0) v = parent_or_size[v];
return v;
}
int size() {
return num_component;
}
int size(int v) {
assert(0 <= v && v < _n);
return -parent_or_size[leader(v)];
}
T max_edge(int u, int v){
T ans = 0;
while(u != v){
if (dat[u] > dat[v]) std::swap(u, v);
ans = dat[u], u = parent_or_size[u];
if(u < 0) return -1;
}
return ans;
}
private:
int _n, num_component;
// root node: -1 * component size
// otherwise: parent
std::vector<int> parent_or_size;
std::vector<T> dat;
};