Problem Solving/알고리즘

코딩테스트에서 자주 쓰는 C++ STL 라이브러리, 자료구조, 알고리즘 정리(1) - 유니온 파인드(Union-Find)

돌돌김 2021. 1. 5. 01:42

Union-Find

Union-Find에 대해 알아보자

유니온 파인드는 자료구조 이므로 단독으로 쓰이기 보다, 알고리즘(크루스칼 등)에 활용된다



  • 기본 개념

    • 유니온 파인드는 '집합'을 관리하는 자료구조이며 서로소 집합(Disjoint Set) 이라고도 불린다.
    • 유니온 파인드를 활용하면 다음과 같은 작업을 할 수 있다.
    • 원소 A와 원소 B가 같은 집합에 속하는지 확인 -- Find 함수
      • 원소 A가 속한 집합과 원소 B가 속한 집합을 병합 -- Union 함수

  • 방식

    • 초기화
    for (int i = 0; i <= n; i++) {
            parent[i] = i; 
        }

    • Union 함수
    void Union(int n1, int n2) {// 부모를 합칠 때는 일반적으로 더 작은 값 쪽으로 합친다
        n1 = Find(n1); 
        n2 = Find(n2);
        // n1<n2 로 가정
        if (n1 != n2) {
            if (n1 < n2)
                parent[n2] = n1;
            else
                parent[n1] = n2;
        }
    }

    • Find 함수
    int Find(int n1) { // n1이 어떤 집합에 포함되어 있는지 찾는 연산
        if (n1 == parent[n1]) {// 루트 노드인 경우
            return n1;
        }
        else {
            return parent[n1] = Find(parent[n1]);
        }
    }

    • 실제 문제 풀이
    int main() {
        ios::sync_with_stdio(false);  cin.tie(0); cout.tie(0);
        freopen("input.txt", "r", stdin);
        cin >> n >> m;
        for (int i = 1; i <= n; i++) {
            parent[i] = i;
        }
        for (int i = 1; i <= m; i++) {
            cin >> n1 >> n2 >> cost;
            graph.push_back({cost,{n1,n2}});
        }
        sort(graph.begin(), graph.end()); // 최소 비용을 구하기 위해 정렬
        int cnt = 0;
        for (int i = 0; i < graph.size(); i++) {
            int cur_cost = graph[i].first;
            int home1 = min(graph[i].second.first, graph[i].second.second);
            int home2 = max(graph[i].second.first, graph[i].second.second);
            if (findParent(home1) != findParent(home2)) { // 부모가 다른 애들만, 합침!!!!    
                mergeParent(home1, home2);
            }        
        }
    }
  • 시간복잡도

    • Union 함수 : O(log N)
    • Find 함수 : O(log N)