概要:
同時検索テンプレート-パス圧縮、ランクに応じた分散
問題の簡単な説明(問題の変換):
nの村があり、mの条件が与えられており、各条件は2つの村が相互に接続されていることを示しています。指定された2つの村が到達可能かどうかを尋ねます(必ずしも直接到達可能である必要はありません)
元の質問へのリンク:Luogu P1536 Village-Village
アルゴリズムの分析:
典型的なユニオンチェックテンプレート。最適化には、パス圧縮とランク割り当てを使用できます。
特に、この質問の出力は制御が簡単ではありません。次の式を使用できます(cin >> n >> m)戻り値を決定します。入力にcinを使用します。入力後にバッファに他のもの(文字、整数など)がない場合は、EOFを返します。EOFしばらくの間は誤りと見なされます
コードと詳細なコメント:
#include <iostream>
#include <stdio.h>
#include <vector>
#pragma warning(disable:4996)
using namespace std;
class UnionFind {
public:
int count;
vector<int> root;
vector<int> rank;
UnionFind(int _count) :count(_count) {
root.resize(_count + 1);
for (int i = 1; i <= _count; ++i)
root[i] = i;
rank.resize(_count + 1, 0);
}
int find(int x) {
return x == root[x] ? x : root[x] = find(root[x]);
}
void merge(int x, int y)
{
int rootx = find(x);
int rooty = find(y);
if (rootx != rooty) {
if (rank[rootx] < rank[rooty])
swap(rootx, rooty);
root[rooty] = rootx;
if (rank[rootx] == rank[rooty]) rank[rootx]++;
--count;
}
}
};
int main() {
//freopen("in.txt", "r", stdin);
int n, m;
while (cin >> n >> m)
{
int x, y;
UnionFind u(n);
for (int i = 1; i <= m; ++i)
{
cin >> x >> y;
u.merge(x, y);
}
cout << u.count-1<<endl;
}
return 0;
}