이 영역을 누르면 첫 페이지로 이동
Arc 블로그의 첫 페이지로 이동

Arc

페이지 맨 위로 올라가기

Arc

[Baekjoon] 16947: 서울 지하철 2호선

  • 2023.06.14 14:00
  • Algorithm/PS
글 작성자: SeoArc

문제

순환선의 특정 역과 순환선이 아닌 역 사이의 거리를 구하는 문제이다.

예를 들면 까치산은 순환선과 거리가 4, 도림천은 거리가 1이다.

 

풀이

내 풀이

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class Q16947 {

    private static int n;

    private static List<List<Integer>> graph;
    private static boolean[] visited;
    private static int[] cycle;
    private static boolean[] check;
    private static int[] distances;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        graph = new ArrayList<>();

        n = Integer.parseInt(br.readLine());
        visited = new boolean[n + 1];
        cycle = new int[n + 1];
        check = new boolean[n + 1];
        distances = new int[n + 1];
        for (int i = 0; i <= n; i++) {
            graph.add(new ArrayList<>());
        }

        for (int i = 0; i < n; i++) {
            String[] input = br.readLine().split(" ");
            int a = Integer.parseInt(input[0]);
            int b = Integer.parseInt(input[1]);
            graph.get(a).add(b);
            graph.get(b).add(a);
        }

        cycle[1] = 1;
        visited[1] = true;
        search(1);

        for (int i = 1; i <= n; i++) {
            if (!check[i]) {
                findDistance(i);
            }
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 1; i < n; i++) {
            sb.append(distances[i]).append(" ");
        }
        sb.append(distances[n]);
        System.out.println(sb);
    }

    public static void findDistance(int start) {
        Deque<int[]> dq = new ArrayDeque<>();
        boolean[] visited = new boolean[n + 1];
        dq.offerLast(new int[]{start, 0});

        while (!dq.isEmpty()) {
            int[] cur = dq.pollFirst();

            for (int next : graph.get(cur[0])) {
                if (visited[next]) {
                    continue;
                }

                if (check[next]) {
                    distances[start] = cur[1] + 1;
                    return;
                }

                visited[next] = true;
                dq.offerLast(new int[]{next, cur[1] + 1});
            }
        }
    }

    public static int search(int cur) {
        int result = -1;
        for (int next : graph.get(cur)) {
            if (next == cycle[cur]) {
                continue;
            }
            if (visited[next]) {
                check[cur] = true;
                return next;
            }
            cycle[next] = cur;
            visited[next] = true;
            int temp = search(next);
            if (temp != -1) {
                result = temp;
                if (result == cur) {
                    check[cur] = true;
                    return -1;
                }
                check[cur] = true;
            }
        }
        return result;
    }
}

결국 먼저 순환선이 무엇인지 먼저 찾아야 한다. 즉, 그래프의 사이클을 찾아야한다.

 

이 사이클을 찾는 유형은 전에 풀이했던 문제에도 포함되어 있는데, 못 풀어봤다면 한 번 풀어보자.

[Baekjoon] 9466: 텀 프로젝트

 

9466번: 텀 프로젝트

이번 가을학기에 '문제 해결' 강의를 신청한 학생들은 텀 프로젝트를 수행해야 한다. 프로젝트 팀원 수에는 제한이 없다. 심지어 모든 학생들이 동일한 팀의 팀원인 경우와 같이 한 팀만 있을

www.acmicpc.net

 

먼저 사이클의 조건 중 하나는 정점(vertex)가 3개 이상 있어야 한다는 것이다. 즉, 2개 이하라면 사이클이 형성될 수 없다.

위에 작성한 내 코드는 이미 방문했던 곳을 만나면 사이클일 거라는 추측으로 구현했다. 때문에 정점이 2개로 형성된 구간이 아니라는 것을 검증하는 로직이 추가되어야 한다.

 

검증 방식은 다음과 같다.

  1. 다음 노드로 넘어갈 때 이전 노드를 계속 저장하면서 간다.
  2. 다음 노드로 넘어간 후 다시 다음노드로 넘어갈 때, 이전 노드가 다음 노드와 같다면 건너뛴다.

 

이렇게 체크하여 사이클을 체크한 후 탐색을 빠져나온다.

 

그리고 사이클이 아닌 정점은 사이클을 만날 때 까지 BFS를 통해 탐색하며 거리를 구한다.

 

회고

이 문제는 사이클이 무조건 1개만 생기기 때문에 풀이가 좀 더 수월했다.

사이클이 여러 개인 문제를 풀어보고 싶다면 위에 링크한 문제를 풀어보자.

저작자표시 (새창열림)

'Algorithm > PS' 카테고리의 다른 글

[Baekjoon] 16985: Maaaaaaaaaze  (0) 2023.06.14
[Baekjoon] 15732: 도토리 숨기기  (1) 2023.06.14
[Baekjoon] 22856: 트리 순회  (0) 2023.06.14
[Baekjoon] 15898: 피아의 아틀리에 ~신비한 대회의 연금술사~  (1) 2023.05.10
[Baekjoon] 21611: 마법사 상어와 블리자드  (0) 2023.05.10

댓글

이 글 공유하기

  • 구독하기

    구독하기

  • 카카오톡

    카카오톡

  • 라인

    라인

  • 트위터

    트위터

  • Facebook

    Facebook

  • 카카오스토리

    카카오스토리

  • 밴드

    밴드

  • 네이버 블로그

    네이버 블로그

  • Pocket

    Pocket

  • Evernote

    Evernote

다른 글

  • [Baekjoon] 16985: Maaaaaaaaaze

    [Baekjoon] 16985: Maaaaaaaaaze

    2023.06.14
  • [Baekjoon] 15732: 도토리 숨기기

    [Baekjoon] 15732: 도토리 숨기기

    2023.06.14
  • [Baekjoon] 22856: 트리 순회

    [Baekjoon] 22856: 트리 순회

    2023.06.14
  • [Baekjoon] 15898: 피아의 아틀리에 ~신비한 대회의 연금술사~

    [Baekjoon] 15898: 피아의 아틀리에 ~신비한 대회의 연금술사~

    2023.05.10
다른 글 더 둘러보기

정보

Arc 블로그의 첫 페이지로 이동

Arc

  • Arc의 첫 페이지로 이동

검색

메뉴

  • 홈
  • 태그
  • 방명록

카테고리

  • 분류 전체보기 (106)
    • Language (28)
      • C++ (0)
      • C# (0)
      • Java (28)
    • Algorithm (47)
      • Algorithm (15)
      • Data Structure (6)
      • PS (26)
    • Computer Science (22)
      • Design Pattern (1)
      • Network (14)
      • OS (7)
    • Game (0)
      • Unity (0)
    • Backend (3)
      • Spring (1)
      • JPA (2)
    • DB (0)
      • SQL (0)
    • DevOps (2)
      • AWS (0)
      • Docker (2)
      • Jenkins (0)
      • Nginx (0)
    • Software Engineering (4)
      • OOP (4)
    • AI (0)
      • Machine Learning (0)
    • Others (0)

최근 글

인기 글

댓글

공지사항

아카이브

태그

  • 그래프
  • algorithm
  • 자바
  • graph
  • network
  • 네트워크
  • 알고리즘
  • java

나의 외부 링크

정보

SeoArc의 Arc

Arc

SeoArc

블로그 구독하기

  • 구독하기
  • RSS 피드

방문자

  • 전체 방문자
  • 오늘
  • 어제

티스토리

  • 티스토리 홈
  • 이 블로그 관리하기
  • 글쓰기
Powered by Tistory / Kakao. © SeoArc. Designed by Fraccino.

티스토리툴바