[JAVA/백준] 1717번: 집합의 표현

👀 문제

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

👊 도전

1. 설계

  1. Union-Find 문제이다.

2. 구현 (성공 코드)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import java.util.*;
import java.io.*;
/**
 * @author HEESOO
 *
 */
class Main {
	static StringBuilder sb;
	static int[] parent;
	public static void main(String[] args) throws IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		
		String[] input=br.readLine().split(" ");
		int n=Integer.parseInt(input[0]);
		int m=Integer.parseInt(input[1]);		

		sb=new StringBuilder();
		parent=new int[n+1]; // i의 최상 부모 저장
		for(int i=1;i<=n;i++) parent[i]=i; // 배열 초기화
		
		for(int i=0;i<m;i++) {
			String[] s=br.readLine().split(" ");
			int a=Integer.parseInt(s[1]);
			int b=Integer.parseInt(s[2]);
			
			if(s[0].equals("0")) union(a, b);
			else check(a, b);
		}
		
		System.out.println(sb.toString());
		
	}
	
	public static void union(int a, int b) {
//		if(a>b) { // a<b이도록 설정
//			int temp=a;
//			a=b;
//			b=temp;
//		}		
		// 최상 부모 찾기
		a=find(a);
		b=find(b);
		// 부모가 다르다면 b의 부모로 a설정하여 둘이 합집합 만들기
		if(a!=b) parent[b]=a;
	}
	
	public static int find(int x) {
		if(parent[x]==x) return x; // 부모가 없을 때
		// x의 최상위 부모 저장 및 리턴
		else return parent[x]=find(parent[x]);
	}
	
	public static void check(int a, int b) {
		a=find(a);
		b=find(b);
		// 최상위 부모가 같아야 둘은 합집합임
		sb.append(a==b? "YES\n":"NO\n");
	}
}

3. 결과

실행결과 🤟 성공 🤟

4. 설명

  1. Union-Find으로 문제를 해결한다
    • parent[]는 i의 부모를 저장한다.
    • 처음에는 부모가 없으므로 자기자신으로 배열을 초기화한다.
  2. Union
    • a와 b를 합집합으로 만든다.
    • 부모가 자식보다 작아야 한다던가의 크기 조건이 없기 때문에 a와 b의 대소 비교는 필요없다(있어도 문제 푸는데 지장은 없다).
    • find()로 a, b의 부모를 찾는다. 둘의 부모가 같다면 이미 합집합이므로 따로 코드를 수행하지 않아도 된다.
    • 부모가 다르다면, b의 부모로 a를 설정한다(a의 부모로 b를 설정해도 상관없다).
  3. Find
    • x의 부모를 찾는다.
    • parent[x]==x라면 더이상 x의 부모가 없는 것이므로 x를 리턴한다.
    • 부모가 더 있다면 재귀 호출을 통해 그곳으로 이동한다.
    • 재귀를 통해 타고타고 최상위 부모까지 갔다가 최상위 부모 값을 가지고 다시 복귀하면, parent[x]에 최상위 부모를 저장한다. 이를 통해 이후 다시 x의 부모를 찾을 때, 똑같이 부모를 타고 올라가는 중복을 방지한다.

👏 해결 완료!

참고