문제
https://www.acmicpc.net/problem/1976
풀이(25분)
import java.util.*;
import java.io.*;
public class Main {
static int[] parent;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
int n = Integer.parseInt(br.readLine()); // 도시의 수
int m = Integer.parseInt(br.readLine()); // 여행 계획 도시 수
// 유니온 파인드 초기화
parent = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
}
// 도시 연결 정보 입력
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < n; j++) {
if (Integer.parseInt(st.nextToken()) == 1) { // 연결되어 있다면
union(i, j); // 두 도시를 같은 집합으로 묶음
}
}
}
// 여행 계획 입력
st = new StringTokenizer(br.readLine());
int firstCity = find(Integer.parseInt(st.nextToken()) - 1); // 첫 번째 도시의 대표
boolean canTravel = true;
for (int i = 1; i < m; i++) {
int nextCity = Integer.parseInt(st.nextToken()) - 1;
if (find(nextCity) != firstCity) { // 다른 대표를 가진 도시 발견
canTravel = false;
break;
}
}
System.out.println(canTravel ? "YES" : "NO");
}
// Find: 대표 노드를 찾는 함수 (경로 압축)
public static int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]); // 경로 압축
}
return parent[x];
}
// Union: 두 집합을 합치는 함수
public static void union(int a, int b) {
int rootA = find(a);
int rootB = find(b);
if (rootA != rootB) {
parent[rootB] = rootA; // 두 집합을 합침
}
}
}
여행의 경로가 중요한 것이 아닌 갈 수 있는지! 만 중요한 것이다. 즉, 동일한 부모를 바라보고 있다면 경로가 가능하다! 라고 결론을 내렸고, 유니온 파인드 알고리즘을 도입하여 문제를 해결할 수 있었다.
1. 모두 자기 자신의 인덱스를 바라보고 있는다.
2. 경로가 있다면 인덱스를 통일한다.(0-1이 연결된 길이 있다면 둘 다 인덱스를 0으로 맞추는 것이다.)
3. 이 과정을 반복한다.
4. 최종적으로 가고자 하는 경로의 인덱스를 보면 된다!
'문제 풀이 > 백준' 카테고리의 다른 글
[백준] 1541번. 잃어버린 괄호(JAVA) (0) | 2024.12.02 |
---|---|
[백준] 1874번. 스택 수열(JAVA) (0) | 2024.12.02 |
[백준] 1759번. 암호 만들기(JAVA) (2) | 2024.11.29 |
[백준] 24723번. 녹색 거탑(JAVA) (0) | 2024.11.29 |
[백준] 15439번. 베라의 패션(JAVA) (0) | 2024.11.29 |