[유니온 앤 파인드] 백준 1717. 집합의 표현
2025. 4. 28. 16:55

유니온앤파인드(Union And Find)

그래프/트리에서 쓰는 대표적인 알고리즘으로, 서로소인 부분집합을 표현한다.

즉, 여러 노드가 있을때 두 노드가 같은 그래프에 있는가?를 판단할 수 있는 알고리즘이다.

union(합치는)연산과 find(어느 집합에 속하는지)연산으로 이루어져있다.

 

 

알고리즘 구현 방법

1. parent[] 배열을 만들고, 각 인덱스에 인덱스값을 넣는다(parent[i] = i, 모든 노드가 자기자신을 부모로 가리킨다)

2. union(a,b)의 경우, a와 b를 합치는 작업을 한다. parent[2]=1이 됨으로써 집합을 표현할 수 있다(더 작은값 쪽으로 합친다)

3. 그러나 이렇게했을경우, 1-2-3이 연결되었을때 parent[1]=1, parent[2]=2, parent[3]=2가 되기 때문에 합집합을 알아보기 힘들다. 따라서 union이전에 find과정을 통해서 부모값을 미리 찾아야한다. 따라서 기본적인 코드는 다음과 같다.

static void make() {
    parents = new int[V];
    for(int i=0; i<V; i++) parents[i] = i;
}

static int find(int a) {
    if(parents[a]==a) return a;
    return parents[a] = find(parents[a]);
}

static boolean union(int a, int b) {
    int aRoot = find(a);
    int bRoot = find(b);
    if(aRoot == bRoot) return false; //싸이클 발생
    parents[bRoot] = aRoot;
    return true;
}

 

 

백준 1717. 집합의 표현

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

 

0이 주어지면 합집합 연산을, 1이 주어지면 두 노드가 같은 집합안에 속하는지 확인하는 연산을 수행한다.

따라서, Union을 통해 0연산을 수행하고, find연산을 통해 1연산을 수행하면 된다.

 

cf)

공간복잡도 : parent배열 크기(n+1) => O(n)

시간복잡도 : make메소드(O(n)) + 유니온앤파인드O(α(n)) => O(m α(n))

 

풀이

1. parent[]함수를 만들어 초기화한다.

2. 모든 명령어를 순회

    2-1. 0일땐 union을 실행

    2-2. 1일땐 find한 후 같은 집합이면 YES, 아니면 NO 누적

 

public class Main {
    static int[] parents;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        StringBuilder sb = new StringBuilder();
        int n = Integer.parseInt(st.nextToken());
        int m = Integer.parseInt(st.nextToken());
        parents = new int[n+1];
        for(int i=0; i<n+1; i++) parents[i] = i;

        for(int i=0; i<m; i++) {
            st = new StringTokenizer(br.readLine());
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());
            int c = Integer.parseInt(st.nextToken());
            if(a == 0) union(b,c);
            else if(a==1) {
                if(find(b) == find(c)) sb.append("YES").append('\n');
                else sb.append("NO").append('\n');
            }
        }
        System.out.println(sb);
    }

    private static boolean union(int a, int b) {
        int aRoot = find(a);
        int bRoot = find(b);

        if(aRoot == bRoot) return false;
        parents[bRoot] = aRoot;
        return true;
    }

    private static int find(int a) {
        if(parents[a] == a) return a;
        return parents[a] = find(parents[a]);
    }
}

'그래프' 카테고리의 다른 글

[위상정렬] 백준 1766. 문제집  (0) 2025.04.25