코딩테스트 사이트 : 백준
난이도 : 골드4
풀이 날짜 : 2022.06.25
사용한 풀이 방법 : UnionFind
https://www.acmicpc.net/problem/1717
예를 들어 각각 독립적으로 자유분방하게 여러 노드가 존재한다고 가정하자
아래 그림은 6개의 노드가 존재하고, 모두 자기 자신을 가리킨다고 할 수가 있다.

1번 노드와 2번 노드가 연결되었다고 해본다.

Union이라고 한다.이번에는 2번과 3번 노드가 연결 되었다고 해보자.

여기서 유니온 파인드의 핵심,
1번 노드와 3번 노드는 같은 그래프에 있는데, 어떻게 연결되었다고 파악할 수 있을까요?
재귀함수로 확인을 한다.
Union-Find라고 한다.코드로 보면 이해가 될 것이다.
// 부모 노드 얻기
public static int getParent(int[] parent, int x){
if(parent[x] == x) return x; // 자기자신을 가리킨다면 반환
return parent[x] = getParent(parent, parent[x]);
}
// 두 부모 노드 합치기
public static void unionParent(int[] parent, int x, int y){
x = getParent(parent, x);
y = getParent(parent, y);
if(x > y) parent[x] = y;
else parent[y] =x ;
}
public static boolean findParent(int[] parent, int x, int y){
x = getParent(parent, x);
y = getParent(parent, y);
return x == y;
//풀어 쓰면,
//if(x==y) return true;
//else return false;
}
이제 작성한 코드를 테스트 해보자
아래와 같이 문제가 주어졌을 때, 풀어 보자

import java.util.Arrays;
public class unionFindTest {
// 부모노드 얻기
public static int getParent(int[] parent, int x){
if(parent[x] == x) return x;
return parent[x] = getParent(parent, parent[x]);
}
// 두 부모 노드 합치기
public static void unionParent(int[] parent, int x, int y){
x = getParent(parent, x);
y = getParent(parent, y);
if(x > y) parent[x] = y;
else parent[y] =x ;
}
// 부모가 같은지 확인 -> 즉, 같이 연결되어 있는지 확인
public static boolean findParent(int[] parent, int x, int y){
x = getParent(parent, x);
y = getParent(parent, y);
return x == y;
}
// 테스트 코드
public static void main(String[] args) {
int[] parent = new int[7];
for(int i =1 ; i< parent.length; i++){
parent[i] = i; // 모든 부모노드 초기화
}
unionParent(parent, 1,2);
unionParent(parent, 2,3);
unionParent(parent, 3,4);
unionParent(parent, 5,6);
findParent(parent, 1,4); // true
findParent(parent, 4,5); // false
}
}
각 부분마다 System.out.println(Arrays.toString(parent)); 넣어주면 아래와 같다.

그래서 결론적으로 parent 배열은 아래와 같이 만들어 진다.
0이면 합집합 연산을, 1이면 같은 집합안에 있는지 유무를 리턴한다.1일때만 하면 된다.

1 1 7로 같은 집합안에 있는지 유무를 파악해야한다. 1 과 7은 연결되어 있지 않음을 알 수 있다 NO를 출력한다.
1 7 1로 같은 집합안에 있는지 유무를 파악해야한다. 1 과 7은 연결되어 있지 않음을 알 수 있다 NO를 출력한다.
1 1 1로 같은 집합안에 있는지 유무를 파악해야한다.1 과 1은 연결되어 있음을 알 수 있다YES를 출력한다. import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
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());
int[] parent = new int[N+1];
for(int i =0 ; i< parent.length; i++){
parent[i] = i;
}
int order;
int x;
int y;
StringBuilder sb =new StringBuilder();
// 한줄 한줄 M번 읽기
for(int i=0; i<M; i++){
st = new StringTokenizer(br.readLine());
order = Integer.parseInt(st.nextToken());
x = Integer.parseInt(st.nextToken());
y = Integer.parseInt(st.nextToken());
if(order == 0){
unionParent(parent, x,y);
}
if(order == 1){
if(findParent(parent,x,y)) sb.append("YES");
else sb.append("NO");
sb.append("\n");
}
}
System.out.println(sb.toString());
br.close();
}
// 부모노드 얻기
public static int getParent(int[] parent, int x){
if(parent[x] == x) return x;
return parent[x] = getParent(parent, parent[x]);
}
// 두 부모 노드 합치기
public static void unionParent(int[] parent, int x, int y){
x = getParent(parent, x);
y = getParent(parent, y);
if(x > y) parent[x] = y;
else parent[y] =x ;
}
// 부모가 같은지 확인 -> 즉 같이 연결되어 있는지 확인
public static boolean findParent(int[] parent, int x, int y){
x = getParent(parent, x);
y = getParent(parent, y);
return x == y;
}
}
