본문 바로가기

CodingTEST

[백준 1976] 여행 가자 (JAVA)

반응형

백준 1976번 문제 - 여행 가자 

 

1976번: 여행 가자

동혁이는 친구들과 함께 여행을 가려고 한다. 한국에는 도시가 N개 있고 임의의 두 도시 사이에 길이 있을 수도, 없을 수도 있다. 동혁이의 여행 일정이 주어졌을 때, 이 여행 경로가 가능한 것인

www.acmicpc.net


문제 분석

 

  • N(전체 도시 개수)하고 M(가고 싶은 도시 개수)을 입력받고,
  • N(1 i ≤ N)번 N(1  j ≤ N)개씩 수가 주어진다.
    이 수는 i번 나라와 j번 나라의 연결 정보 입력 정보로 1이면 i와 j 나라가 연결되있음을 의미
  • 가고 싶은 도시 M개를 입력 받는다.
  • 가고 싶은 도시들이 다 연결되어 있어 모두 갈 수 있을 경우 YES, 아닐 경우 NO 출력

해결 키 포인트

 

  • 유니온 파인드(union-find) 개념 사용
  • i 나라와 j 나라가 연결 정보가 1일때, 무조건적으로 union(i, j)를 하면 안된다.
    WHY? 중복이 존재하기 때문 ➡️ 이미 처리한 나라인지 확인 후 확인 안할 경우 union(i, j) 실행
    • 이미 처리한 나라인지 : i 나라와 j 나라가 동일한 집합이면 이미 처리한 나라
    • find(a) != find(b) 여야지 union(i, j) 실행

유니온 파인트 (union-find)

여러 노드가 있을 때 특정 2개의 노드를 연결해 1개의 집합으로 묶는 union 연산과 두 노드가 같은 집합에 속해 있는지 확인하는 find 연산으로 구성되어 있는 알고리즘이다.

 

  • union 연산 : 각 노드가 속한 집합을 1개로 합치는 연산이다. 노드 a, b가 a ∈ A, b ∈ B일 때 union(a, b)는 A∪B를 말한다.
  • find 연산 : 특정 노드 a에 관해 a가 속한 집합의 대표 노드를 반환하는 연산이다. 노드 a, b가 a ∈ A일 때 find(a)는 A 집합의 대표 노드를 반환한다. 

 

Union 연산 알고리즘
  • 1차원 배열을 이용해서, i번째 값은 i로 변수 초기화한다. ( 대표 노드는 본인 )
  • union(a, b) 연산은 a와 b의 대표 노드를 알아내 'b 대표 노드'의 value( list['b 대표 노드'] )을 'a 대표 노드'로 변경한다.
    • index == list[index] : 해당 index가 집합의 대표 노드
      index !=  list[index] : 대표 노드를 알아내야 함 ( 배열의 list[index]와 list[list[index]] 비교 )
    • list['b 대표 노드'] = 'a 대표 노드' 로 b 집합을 a 집합에 포함시킨다.

 

Find 연산 알고리즘
  • 대상 노드 배열에 index 값과 value 값이 동일한지 확인
  • 동일하지 않으면 value 값이 가리키는 index 위치로 이동
  • 이동 위치의 index 값과 value 값이 같을 때까지 앞 방법들을 반복 (재귀함수로)
  • 대표 노드에 도달하면 재귀함수를 빠져나오면서 거치는 모든 노드 값을 대표 노드 값으로 변경

코드

 

import java.io.*;
import java.util.*;

public class Main {
    public static int [] collection;
    public static void main(String [] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        // N,M 입력
        int N = Integer.parseInt(br.readLine());
        int M = Integer.parseInt(br.readLine());

        // N개의 집합 생성
        collection = new int [N+1];
        for(int i=0;i<=N;i++) {
            collection[i] = i;
        }

        // N개의 도시 연결 정보
        for(int i=1;i<=N;i++) {
            StringTokenizer st = new StringTokenizer(br.readLine());
            for(int j=1;j<=N;j++) {
                // isContain: 1이면 i번과 j번이 연결 O, 0이면 연결 X
                int isContain = Integer.parseInt(st.nextToken());
                if (isContain == 1 && find(i) != find(j)) {
                    union(i, j);
                }
            }
        }

        // M개의 가고 싶은 나라 입력
        StringTokenizer st = new StringTokenizer(br.readLine());
        boolean isTripPossible = true;
        int country = Integer.parseInt(st.nextToken());
        for(int i=0;i<M-1;i++) {
            int gotoCountry = Integer.parseInt(st.nextToken());
            if(find(country) != find(gotoCountry)) {
                isTripPossible = false;
                break;
            }
        }

        // 만약 isTripPossible가 true면 모두 여행 가능, 아니면 불가능
        if(isTripPossible)
            bw.write("YES");
        else
            bw.write("NO");
        bw.flush();
        bw.close();
    }

    public static void union(int a, int b) {
        int firstA = a, firstB = b;

        // a가 집합 대표가 아닐 경우 (a와 collection[a]가 동일 하지 않을 경우)
        if(a != collection[a])
            firstA = find(a); //  a 집합 대표 찾기 ( find(a) )


        // b가 집합 대표가 아닐 경우 (b와 collection[b]가 동일 하지 않을 경우)
        if(b != collection[b])
            firstB = find(b); //  b 집합 대표 찾기 ( find(b) )

        // b 집합의 대표를 a 집합의 대표로
        collection[firstB] = firstA;
    }

    public static int find(int a) {
        // a가 집합 대표일 경우 (a와 collection[a]가 동일 할 경우)
        if (a == collection[a])
            return a;

        //  a가 집합 대표가 아닐 경우
        collection[a] = find(collection[a]);
        return collection[a];
    }
}
 
 
반응형

'CodingTEST' 카테고리의 다른 글

[백준 2252] 줄 세우기 (JAVA)  (1) 2023.08.27
[백준 1043] 거짓말 (JAVA)  (1) 2023.08.27
[백준 1717] 집합의 표현 (JAVA)  (2) 2023.08.26
[백준 2251] 물통 (JAVA)  (0) 2023.08.25
[백준 1707] 이분 그래프 (JAVA)  (0) 2023.08.24