본문 바로가기
알고리즘/백준 문제풀이

백준 [자바 java] 1717번 : 집합의 표현

by 잔디🌿 2023. 7. 13.

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

     

    1717번: 집합의 표현

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

    www.acmicpc.net

     

    이 문제는 유니온파인드를 사용하여 풀었다. 옛날에는 유니온파인드가 복잡하고 별로라고 생각했는데, 난이도가 올라갈수록 집합문제에 이 알고리즘을 안쓰면 시간초과, 메모리초과 없이 문제를 풀 수가 없다. 

    처음에는 find함수에서 return할 때 재귀로 받은 값을 union[k]에 넣는 것을 생략했는데, 이랬더니 시간초과가 났다.

    앞으로는 귀찮다고 생략하지 말자.

     

    풀이방법

    • 전역변수로 union배열 생성
    • find함수를 만든다.(union[k] == k일 때까지 재귀로 돌려준다)
    • 메인에서 요소의 갯수만큼 배열 할당해주고, union에 각각 본인의 수 넣어준다.
    • m번 세 수를 입력받는다.
    • 이때 첫번째 수가 1이면 두번째 , 세번째 수를 find해주어 값을 비교하고 두 수가 같으면 같은 집합이라는 의미이므로 yes를, 아니면 no를 출력한다.
    • 0이면 b와 c를 find 해주고 이 들중 작은 수의 union에 큰 수를 넣어준다.

     

    풀이코드

    import java.util.*;
    import java.io.*;
    import java.math.*;
    
    
    public class Main {
    
        static int[] union;
    
        static int find(int k){
            if(union[k] == k){
                return k;
            }
            else return union[k] = find(union[k]);
        }
    
    
        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());
    
            union = new int[n+1];
    
            for(int i = 0;i<=n;i++){
                union[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 == 1){
                    if(find(b) == find(c)){
                        sb.append("YES").append("\n");
                    }
                    else{
                        sb.append("NO").append("\n");
                    }
                }
                else{
                    int first = find(b);
                    int second = find(c);
                    if(first < second) union[first] = second;
                    else union[second] = first;
                }
            }
    
            System.out.println(sb);
    
        }
    }