メソッド ~機能~
メソッド名 | 機能 |
---|---|
get_root_number | 根の番号の取得 |
merge | 二つの部分木を結合 |
is_same_tree | 同じ部分木(グループ)に属するかどうか true:属する false:属さない |
get_subtree_size | 「引数として与えられたノード」を含む部分木のサイズを取得 |
namespace template_data_structure {
class union_find {
public:
/** @brief default constructor */
union_find() = default;
/**
* @brief constructor
* @param node_count 頂点数
*/
union_find(int node_count) : parent(std::vector<int>(node_count, root_parent_number)), subtree_size(std::vector<int>(node_count, 1)) {}
/** @brief x番のノードが含まれる木の"根の番号"を取得 */
int get_root_number(int x) {
if (parent[x] == root_parent_number) return x;
else return parent[x] = get_root_number(parent[x]);
}
/** @brief x, y番のノード同士を併合する */
void merge(int x, int y) {
int root_of_x = get_root_number(x);
int root_of_y = get_root_number(y);
if (root_of_x == root_of_y) return;
if (subtree_size[root_of_x] > subtree_size[root_of_y]) merge_operation(root_of_x, root_of_y);
else merge_operation(root_of_y, root_of_x);
}
/**
* @brief x, y番のノードが同じ部分木に属するか
* @return true:属する false:属さない
*/
bool is_same_tree(int x, int y) {
return get_root_number(x) == get_root_number(y);
}
/** @brief x番のノードが含まれる部分木のサイズを取得する */
int get_subtree_size(int x) {
return subtree_size[get_root_number(x)];
}
private:
/** @brief 根の親を表す無効な値 */
const int root_parent_number = -1;
std::vector<int> parent;
/** @brief subtree_size[i]:= iを根とした部分木のサイズ(iが根でない場合はアクセスされない) */
std::vector<int> subtree_size;
/**
* @brief 併合操作
* より大きい方の根に、小さい方の部分木を併合する
* 部分木サイズも更新する
*/
std::function<void(int, int)> merge_operation = [&](int bigger_root, int smaller_root) {
parent[smaller_root] = bigger_root;
subtree_size[bigger_root] += subtree_size[smaller_root];
};
};
}
行った高速化の工夫
- “経路圧縮“
- “サイズ による合併“
と、言われるやつのようです…
(以下の記事でそのように呼ばれていたので…その呼び方を使わせていただきます)
参考になった記事
Union-Find Tree を理解する!素集合系を扱うデータ構造 | アルゴリズムロジック
2つの集合が共通する要素を持たない時に「互いに素」であると言い、このような集合の集まりを「素集合系」などと言います。 素集合系の例 素集合系は、いくつかの木構造を用いることで管理...
いくつかの使用例 (C++)
いくつかの問題をC++でACしたので提出を置いておきます✨✨
Submission #59496560 - AtCoder Beginner Contest 177
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
Submission #59496472 - AtCoder Beginner Contest 378
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
Submission #59496524 - AtCoder Regular Contest 106
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
さいごに
とりあえず、必要最小限のみの実装となっています。
(まだいくつかほしい機能があるので、また追記する予定です)
AtCoderの問題でもUnionFindは結構でてくるので、よければ使ってくださいね🥰🥰
もし、「このコード使ったよ」(←励みになります)や「正しく動かないよ」ということがありましたら筆者のX(旧Twitter)まで連絡いただけると助かります。
最後までお読みいただきありがとうございましたっ
( ゚д゚)つ Bye
コメント