Coding Test/백준

[백준] 1717 집합의 표현 - 자바

lsh2613 2023. 9. 17. 14:22

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

 

1717번: 집합의 표현

초기에 $n+1$개의 집합 $\{0\}, \{1\}, \{2\}, \dots , \{n\}$이 있다. 여기에 합집합 연산과, 두 원소가 같은 집합에 포함되어 있는지를 확인하는 연산을 수행하려고 한다. 집합을 표현하는 프로그램을 작

www.acmicpc.net

문제 풀이

각 값들이 어떤 집합의 속하는지를 구분하기 위해 집합의 기준이 되는 노드를 정해야 한다. 필자는 가장 작은 값을 그룹의 기준값으로 정하였고 이 로직을 구현하기 위해 union-find 알고리즘을 적용시켰다. union-find에 대한 설명은 이 글을 참고바란다. 

하지만 이 문제에선 바로 합치는 개념이 아니라 0이면 합치고 1이면 그룹의 속해있는지 여부를 알아내야 하기 때문에 기존 union 메소드에서 사이클이 생기는지(= 같은 집합인지)에 대한 검증 로직을 따로 빼내어 unionCheck()메소드를 만들었다

static void union(int a, int b) {
    int aAncestor = findAncestor(a);
    int bAncestor = findAncestor(b);

    // 루트 노드는 작은 값으로 지정
    if (aAncestor > bAncestor)
        ancestor[aAncestor] = bAncestor;
    if (aAncestor < bAncestor)
        ancestor[bAncestor] = aAncestor;

}
static boolean unionCheck(int a, int b) {
    int aAncestor = findAncestor(a);
    int bAncestor = findAncestor(b);

    if (aAncestor == bAncestor) // 같으면 순환
        return true;

    return false;
}

 

코드

package 백준;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class b1717 {
    static int[] ancestor;

    public static void main(String[] args) throws IOException {
        StringBuilder sb = new StringBuilder();
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        StringTokenizer st = new StringTokenizer(br.readLine());
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());

        // init
        ancestor = new int[N+1];
        for (int i = 1; i <= N; i++) {
            ancestor[i] = i;
        }

        for (int i = 1; i <= M; i++) {
            st = new StringTokenizer(br.readLine());
            int op = Integer.parseInt(st.nextToken());
            int from = Integer.parseInt(st.nextToken());
            int to = Integer.parseInt(st.nextToken());

            switch (op) {
                case 0:
                    union(from, to);
                    break;
                case 1:
                    boolean unionFlag = unionCheck(from, to);
                    if (unionFlag) {
                        sb.append("YES\n");
                        break;
                    }
                    sb.append("NO\n");
            }
        }
        System.out.println(sb);
    }

    static void union(int a, int b) {
        int aAncestor = findAncestor(a);
        int bAncestor = findAncestor(b);

        // 루트 노드는 작은 값으로 지정
        if (aAncestor > bAncestor)
            ancestor[aAncestor] = bAncestor;
        if (aAncestor < bAncestor)
            ancestor[bAncestor] = aAncestor;

    }
    static boolean unionCheck(int a, int b) {
        int aAncestor = findAncestor(a);
        int bAncestor = findAncestor(b);

        if (aAncestor == bAncestor) // 같은 집합
            return true;

        return false;
    }

    static int findAncestor(int n) {
        if (n != ancestor[n]) {  // 루트 노드가 아니라면
            ancestor[n] = findAncestor(ancestor[n]);
        }
        return ancestor[n];
    }
}