알고리즘/백준 문제풀이

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

잔디🌿 2023. 7. 13. 03:47

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);

    }
}