유니온 파인드(Union find) & 서로소 집합(Disjoint Set)?
Union find는 대표적인 그래프 알고리즘으로
집합 내의 요소의 연결성을 효율적으로 추적하는 데 사용되는 데이터 구조 및 알고리즘입니다.
역으로 서로 연결되어 있지 않은 노드를 판별할 수도 있기 때문에 서로소 집합 (Disjoint-set)이라고도 합니다.
알고리즘은 union과 find의 두 가지 연산으로 구성되어 있습니다.
-> union 은 각 노드가 속한 집합을 1개로 합치는 연산
-> find 특정 노드 A에 관해 A가 속한 대표 노드를 반환하는 연산
Union-Find 알고리즘은 집합 내 요소의 연결성을 추적하는 데 유용한 데이터 구조 및 알고리즘입니다.
이것은 많은 그래프 알고리즘에서 사용될 수 있으며 경로 압축 최적화로 O(log n) ~ O(n)의 시간 복잡도를 가집니다.
예제 코드 C++
#include <iostream>
#include <vector>
using namespace std;
// Initialize the parent array
void makeSet(int parent[], int n) {
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}
// Find the root of the set containing node x
int find(int parent[], int x) {
if (parent[x] != x) {
parent[x] = find(parent, parent[x]); // Path compression
}
return parent[x];
}
// Merge the sets containing nodes x and y
void unite(int parent[], int x, int y) {
int rootX = find(parent, x);
int rootY = find(parent, y);
parent[rootY] = rootX; // Make rootX the parent of rootY
}
int n = 5; // Number of nodes
int parent[5]; // Number of nodes
int main() {
makeSet(parent, n); // Initialize the parent array
// Merge sets containing nodes 2 and 4
unite(parent, 2, 4);
// Merge sets containing nodes 1 and 5
unite(parent, 1, 5);
// Merge sets containing nodes 1 and 2
unite(parent, 1, 2);
// Find the set of node 4
int root4 = find(parent, 4);
// Print the parent array
for (int i = 0; i < n; i++) {
cout << parent[i] << " ";
}
cout << endl;
// Print the root of the set containing node 4
cout << "The root of the set containing node 4 is " << root4 << endl;
return 0;
}

백준 예제
https://www.acmicpc.net/problem/1717

#include <iostream>
using namespace std;
constexpr int Max = 1000001;
// 유니온 root노드 배열
int uArr[Max];
int N, M, u, b, c;
//부모를 찾는 함수
//모든 경로가 부모를 가르키게 함
//상수 시간의 복잡도
int Find(int x)
{
if (uArr[x] == x) return x;
return uArr[x] = Find(uArr[x]);
}
//두 노드를 연결 시키는 것
//기준을 정해서 연결시키는 것이 헷갈리지 않음
//작은쪽이 부모 or 큰쪽이 부모
void Union(int x, int y)
{
x = Find(x);
y = Find(y);
if (x != y) {
if (x < y) uArr[y] = x;
else uArr[x] = y;
}
}
int main()
{
ios_base::sync_with_stdio(false); // scanf와 동기화를 비활성화
// cin.tie(null); 코드는 cin과 cout의 묶음을 풀어줍니다.
cin.tie(NULL);
cout.tie(NULL);
cin >> N >> M;
// 유니온 배열 초기화
for (int i = 0; i <= N; i++) uArr[i] = i;
for (int i = 0; i < M; i++) {
cin >> u >> b >> c;
if (u == 0) { // 합집합 연산
Union(b, c);
}
else { // 질의
if (Find(b) != Find(c)) cout << "NO\n";
else cout << "YES\n";
}
}
return 0;
}



