This documentation is automatically generated by online-judge-tools/verification-helper
#include "src/dataStructure/potentialized_unionfind.hpp"
直線上のN
個の点について、点A
が点B
より正方向にd
だけ離れているといった情報を保持できるデータ構造です。
UnionFindアルゴリズムを応用することで実装しています。
potentialized_unionfind<cost_type> (std::size_t n)
cost_type
: d
の型
n
:点数N
int leader(int x)
x
が属する根付き木の根を返しますx
: $0\ \le\ x\ \le\ n$bool same(int x, int y)
x
と点y
が連結かを返しますx
: $0\ \le\ x\ \le\ n$y
: $0\ \le\ y\ \le\ n$bool merge(int x, int y, cost_type w)
x
から正方向にw
離れた所に点y
がある」という情報を追加します。
test/potentialized_unionfind3.test.cpp
みたいな感じで別途処理してくださいx
: $0\ \le\ x\ \le\ n$y
: $0\ \le\ y\ \le\ n$same(x, y) == false
の時この関数はtrue
を返しますcost_type diff(int y, int x)
x
から点y
へ正方向にどれだけ離れているかを返します。
same(x, y) == false
の時の動作は未定義です。x
: $0\ \le\ x\ \le\ n$y
: $0\ \le\ y\ \le\ n$重み付き Union-Find 木とそれが使える問題のまとめ、および、牛ゲーについて
#pragma once
#include <vector>
#include <utility>
namespace zawa {
template <class cost_type>
class potentialized_unionfind {
private:
std::vector<int> parents;
std::vector<int> sizes;
std::vector<cost_type> weights;
int rooting(int x) {
if (parents[x] == x) {
return x;
}
else {
int root = rooting(parents[x]);
weights[x] += weights[parents[x]];
return parents[x] = root;
}
}
cost_type get_weight(int x) {
rooting(x);
return weights[x];
}
public:
potentialized_unionfind(std::size_t n) : parents(n, 0), sizes(n, 1), weights(n) {
for (std::size_t i = 0 ; i < n ; i++) {
parents[i] = i;
}
}
int leader(int x) {
return rooting(x);
}
bool same(int x, int y) {
return rooting(x) == rooting(y);
}
bool merge(int x, int y, cost_type w) {
w += get_weight(x);
w -= get_weight(y);
int rx = rooting(x), ry = rooting(y);
if (rx == ry) {
return false;
}
if (sizes[rx] < sizes[ry]) {
std::swap(rx, ry);
w *= -1;
}
sizes[rx] += sizes[ry];
parents[ry] = rx;
weights[ry] = w;
return true;
}
cost_type diff(int y, int x) {
return get_weight(y) - get_weight(x);
}
};
} // namespace zawa
#line 2 "src/dataStructure/potentialized_unionfind.hpp"
#include <vector>
#include <utility>
namespace zawa {
template <class cost_type>
class potentialized_unionfind {
private:
std::vector<int> parents;
std::vector<int> sizes;
std::vector<cost_type> weights;
int rooting(int x) {
if (parents[x] == x) {
return x;
}
else {
int root = rooting(parents[x]);
weights[x] += weights[parents[x]];
return parents[x] = root;
}
}
cost_type get_weight(int x) {
rooting(x);
return weights[x];
}
public:
potentialized_unionfind(std::size_t n) : parents(n, 0), sizes(n, 1), weights(n) {
for (std::size_t i = 0 ; i < n ; i++) {
parents[i] = i;
}
}
int leader(int x) {
return rooting(x);
}
bool same(int x, int y) {
return rooting(x) == rooting(y);
}
bool merge(int x, int y, cost_type w) {
w += get_weight(x);
w -= get_weight(y);
int rx = rooting(x), ry = rooting(y);
if (rx == ry) {
return false;
}
if (sizes[rx] < sizes[ry]) {
std::swap(rx, ry);
w *= -1;
}
sizes[rx] += sizes[ry];
parents[ry] = rx;
weights[ry] = w;
return true;
}
cost_type diff(int y, int x) {
return get_weight(y) - get_weight(x);
}
};
} // namespace zawa