https://www.acmicpc.net/problem/1976
1976번: 여행 가자
동혁이는 친구들과 함께 여행을 가려고 한다. 한국에는 도시가 N개 있고 임의의 두 도시 사이에 길이 있을 수도, 없을 수도 있다. 동혁이의 여행 일정이 주어졌을 때, 이 여행 경로가 가능한 것인
www.acmicpc.net
코드설명
유니온 파인드(Union Find) 문제입니다.
각 정점들이 같은 그래프내에 있는지만 확인하면 되기에 유니온 파인드를 활용하여 해당 그래프들이 같은 그룹에 있는지 확인합니다.
유의해야하는점은
//int ParentValue = parent[plan[0] - 1]; int ParentValue = findParent(plan[0] - 1); for(int i=1;i<M;i++) { //if(ParentValue != parent[plan[i] - 1]) { if(ParentValue != findParent(plan[i] - 1)) { System.out.println("NO"); return ; } }
- Parent[] 를 통해 접근하면 정답이 아니고, findParent를 통해 접근해야만 올바르게 통과합니다.
- 물론, findParent를 통해서 Parent값을 갱신하며 진행할 수 있지만, 왜 Parent로 접근하여 비교한다면 올바른 정답이 아닌것인가라는 의문이 생깁니다. Parent[i] 로 접근하나, findParent[i]로 접근하나 결과값은 동일하다고 생각할 수 있습니다.
- 하지만, 만약 더 낮은 Index의 값이 나중에 들어왔다고 할경우 이전에 unionParent한 값의 parent배열은 변경되지 않으므로 새롭게 findParent를 통해 parent를 갱신시켜야합니다.
또한 추가로, 시간을 더 감소시키기 위해서
for(int i=1; i<=N;i++) { st = new StringTokenizer(br.readLine()); for(int j=1; j<=i;j++) { arr[i][j] = Integer.parseInt(st.nextToken()); if(arr[i][j] == 1) { unionParent(i, j); } } }
입력으로 주어진 도시의 연결정보에서 대각선 기준으로 대칭모양이므로 위와 같이 j<=i 로만 처리하여 중복결과를 피할 수 있습니다.
0 1 0 1 0 1 0 1 0
정답을 구할때는 처음에 주어진 여행게획을 Parent Value로 입력받고, 그 이후에 여행계획들이 Parent Value와 다르다면 같이 분리집합이 아니므로 실패처리합니다.
코드
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.*; public class Main { public static int N, M; public static int answer = 0; public static int[][] arr; public static int[] parent; public static void main(String[] args) throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); N = Integer.parseInt(st.nextToken()); st = new StringTokenizer(br.readLine()); M = Integer.parseInt(st.nextToken()); arr = new int[N+1][N+1]; parent = new int[N+1]; for(int i=1;i<=N;i++) { parent[i] = i; } for(int i=1; i<=N;i++) { st = new StringTokenizer(br.readLine()); for(int j=1; j<=i;j++) { arr[i][j] = Integer.parseInt(st.nextToken()); if(arr[i][j] == 1) { unionParent(i, j); } } } for(int i=1; i<=N;i++) { findParent(i); } st = new StringTokenizer(br.readLine()); int storeParent = parent[Integer.parseInt(st.nextToken())]; for(int i=2;i<=M;i++) { if(storeParent != parent[Integer.parseInt(st.nextToken())]) { System.out.println("NO"); return ; } } System.out.println("YES"); } public static int findParent(int x) { if(x == parent[x]) return x; return parent[x] = findParent(parent[x]); } public static void unionParent(int a, int b) { a = findParent(a); b = findParent(b); if(a < b) { parent[b] = a; }else { parent[a] = b; } } }
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.*; public class Main { public static int N, M; public static int[][] arr; public static int[] plan; public static int[] parent = new int[201]; public static int findParent(int x) { if( x == parent[x]) return x; return parent[x] = findParent(parent[x]); } public static void unionParent(int a, int b) { a = findParent(a); b = findParent(b); if( a < b ) parent[b] = a; else parent[a] = b; } public static void main(String[] args) throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); N = Integer.parseInt(st.nextToken()); st = new StringTokenizer(br.readLine()); M = Integer.parseInt(st.nextToken()); arr = new int[N][N]; // parent = new int[N]; for(int i=0;i<N;i++) { parent[i] = i; } // for(int i=0;i<N;i++) { // System.out.print(" "+parent[i]); // } for(int i=0;i<N;i++) { st = new StringTokenizer(br.readLine()); for(int j=0;j<N;j++) { arr[i][j] = Integer.parseInt(st.nextToken()); } } for(int i=0;i<N;i++) { for(int j=0;j<=i;j++) { if(arr[i][j] == 1) { unionParent(i, j); } } } st = new StringTokenizer(br.readLine()); plan = new int[M]; for(int i=0;i<M;i++) { plan[i] = Integer.parseInt(st.nextToken()); } if( M < 0) System.out.println("YES"); // int ParentValue = parent[plan[0] - 1]; int ParentValue = findParent(plan[0] - 1); // //만약 더 낮은 Index의 값이 나중에 들어왔다고 할경우 이전에 unionParent한 값의 parent배열은 변경되지 않으므로 새롭게 findParent를 통해 parent를 갱신시켜야합니다. for(int i=1;i<M;i++) { // if(ParentValue != parent[plan[i] - 1]) { if(ParentValue != findParent(plan[i] - 1)) { // //만약 더 낮은 Index의 값이 나중에 들어왔다고 할경우 이전에 unionParent한 값의 parent배열은 변경되지 않으므로 새롭게 findParent를 통해 parent를 갱신시켜야합니다. System.out.println("NO"); return ; } } System.out.println("YES"); } }
'알고리즘 > Disjoint Set' 카테고리의 다른 글
[백준] 4195 친구 네트워크 - 유니온파인드(Union Find) + 해쉬맵(HashMap) JAVA (0) | 2023.09.05 |
---|---|
[백준] 16562 친구비 - 유니온파인드(Union Find) + 최소조건(Minimum) JAVA (0) | 2023.09.05 |
[백준] 1717 집합의 표현 - 유니온파인드(Union Find) JAVA (0) | 2023.09.05 |
[백준] 1043 거짓말 - 유니온파인드(Union Find) JAVA (0) | 2023.08.27 |
[백준] 3197 백조의 호수 - BFS(너비우선탐색) + 유니온파인드(Union Find) JAVA (0) | 2023.08.25 |