This documentation is automatically generated by online-judge-tools/verification-helper
#include "data_structure/unionfind_with_potential.hpp"
ポテンシャル付きUnionFind。ここで、 $\alpha(N)$ をアッカーマン関数の逆関数とする。
$x$ と $y$ が同じグループか判定。 $O(\alpha(N))$
$x$ のグループと $y$ のグループをマージ。ポテンシャルは $potential(x) = potential(y) + p$ とする。 $O(\alpha(N))$
$x$ のグループの代表を返す。 $O(\alpha(N))$
$x$ のグループのサイズを返す。 $O(\alpha(N))$
$x$ のポテンシャルを返す。 $O(\alpha(N))$
$x$ と $y$ のポテンシャルの差分を返す。 $O(\alpha(N))$
#pragma once
#include <cassert>
#include <vector>
namespace ebi {
template <class T> struct unionfind_with_potential {
public:
unionfind_with_potential(int n) : data_(n, -1), potential_(n, T()) {}
bool same(int x, int y) {
return leader(x) == leader(y);
}
// potential(x) = potential(y) + p
bool merge(int x, int y, T p) {
p = potential(x) - p - potential(y);
x = leader(x);
y = leader(y);
if (x == y) return p == T();
if (data_[x] > data_[y]) {
std::swap(x, y);
p = -p;
}
data_[x] += data_[y];
data_[y] = x;
potential_[y] = p;
return true;
}
int leader(int x) {
if (data_[x] < 0) return x;
int l = leader(data_[x]);
potential_[x] = potential_[data_[x]] + potential_[x];
return data_[x] = l;
}
int size(int x) {
return -data_[leader(x)];
}
T potential(int x) {
leader(x);
return potential_[x];
}
T diff(int x, int y) {
return potential(x) - potential(y);
}
private:
std::vector<int> data_;
std::vector<T> potential_;
};
} // namespace ebi
#line 2 "data_structure/unionfind_with_potential.hpp"
#include <cassert>
#include <vector>
namespace ebi {
template <class T> struct unionfind_with_potential {
public:
unionfind_with_potential(int n) : data_(n, -1), potential_(n, T()) {}
bool same(int x, int y) {
return leader(x) == leader(y);
}
// potential(x) = potential(y) + p
bool merge(int x, int y, T p) {
p = potential(x) - p - potential(y);
x = leader(x);
y = leader(y);
if (x == y) return p == T();
if (data_[x] > data_[y]) {
std::swap(x, y);
p = -p;
}
data_[x] += data_[y];
data_[y] = x;
potential_[y] = p;
return true;
}
int leader(int x) {
if (data_[x] < 0) return x;
int l = leader(data_[x]);
potential_[x] = potential_[data_[x]] + potential_[x];
return data_[x] = l;
}
int size(int x) {
return -data_[leader(x)];
}
T potential(int x) {
leader(x);
return potential_[x];
}
T diff(int x, int y) {
return potential(x) - potential(y);
}
private:
std::vector<int> data_;
std::vector<T> potential_;
};
} // namespace ebi