알고리즘/이론

[알고리즘] - UnionFind

파커초 2024. 2. 5. 20:16

개요

Union-Find 는 그래프 G가 주어졌을때 상호 배타적 집합(Disjoint-Set)을 표현할때 사용되는 그래프 알고리즘입니다. 임의의 두 노드가 서로 같은 그래프에 속하는지 판별하기 위해 사용됩니다.

연산

  • Union (합치기): 두 원소가 속한 집합을 하나로 합침
  • Find (찾기): 해당 원소가 속한 집합을 반환

Find

본인이 속한 집합을 찾기 위한 연산으로 기본 방법과 경로 최적화 방법이 존재합니다.

기본 방법: 최악의 경우 시간복잡도 O(N)

int find_parent(int x) {
  if(x == parent[x]) return x;
  else return find_parent(parent[x]);
}

경로 최적화: 시간복잡도 O(1)

int find_parent(int x) {
  if(x == parent[x]) return x;
  // 검색과 동시에 초기화
  else return parent[x] = find_parent(parent[x]);
}

Union

기본 방법: 기준을 정하고 기준대로 노드의 부모를 합칩니다. => 집합을 트리로 구성했을때 한쪽으로 치우칠 수 있습니다.

// 작은 수를 기준으로 부모 노드를 설정할때
void union_parent(int a, int b) {
  int a = find_parent(a);
  int b = find_parent(b);
  if(b > a) {
    parent[b] = a;
  }
  else{
    parent[a] = b;
  }
}

최적화 방법: rank 에 트리의 높이를 저장함, 항상 높이가 더 낮은 트리를 밑에 넣음 => 집합을 트리로 구성했을때 어느정도의 balance 를 보장할 수 있습니다.

void union_parent(int a,int b) {
  int a = find_parent(a);
  int b = find_parent(b);
  if(a == b) return;
  
  if(rank[a] < rank[b]) {
    parent[a] = b
  }else if(rank[b] > rank[a]){
    parent[b] = a;
  }else{
    parent[b] = a;
    ++rank[a];
  }
}

관련 문제

https://www.acmicpc.net/problem/4195