[Python] 백준 1948 임계경로

2022. 8. 22. 16:07·CS/알고리즘 & 문제풀이

문제 링크 : https://www.acmicpc.net/problem/1948

 

1948번: 임계경로

첫째 줄에 도시의 개수 n(1 ≤ n ≤ 10,000)이 주어지고 둘째 줄에는 도로의 개수 m(1 ≤ m ≤ 100,000)이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 도로의 정보가 주어진다. 처음에는 도로의

www.acmicpc.net

 

1. 접근 방법

 기본적으로 최단 경로를 찾아야 하는 문제인데, 추가적인 조건이 있어서 접근이 조금 까다로웠다. 시작점부터 도착지까지 최대 시간을 구하는 것은 어렵지 않게 해결할 수 있다. 모든 모로를 확인하며 더 늦은 시간으로 갱신하면 된다. 하지만, '이런 사람들이 지나는 도로의 수를 카운트하여라' 부분에서 시간이 걸렸다.

 문제에서 말한 문장은 수정이 필요해보이지만, 우선 문제 해결과 관련하여 저 말을 더 풀어본다면 다음과 같다. 출발지에서 도착지까지 최대 시간을 구하고, 해당 시간으로 도달할 수 있는 모든 도로의 개수를 세야 한다. 그런데 아래와 같은 예시가 있을 수 있다.

 

 위와 같은 도로에서 1에서 시작하여 5까지 가는 것이 목표이고, 모든 도로 이동에 걸리는 시간이 1로 같다고 할 때, 최단 시간은 3이 되는 것을 알 수 있다. 그리고 3의 시간으로 가는 경로는 2가지이지만, 사용하는 도로의 개수는 1→2→3→5, 1→2→4→5로 6개가 아니라 중복 없이 5개가 돼야 한다. 이 부분을 해결하기 위해 도착지까지 가는 길은 위상 정렬로, 그 도로의 수를 확인하기 위해서는 BFS를 활용했다.


2. 풀이 코드

🖥python 코드 링크 : https://github.com/mintropy/PS/blob/master/BAEKJOON/Python/1000/1900/1948.py

 

GitHub - mintropy/PS: 다양한 알고리즘 문제 풀이 저장소입니다.

다양한 알고리즘 문제 풀이 저장소입니다. Contribute to mintropy/PS development by creating an account on GitHub.

github.com

📕코드 해설

 두가지 작업을 위하여 크게 2개의 while문으로 구성했고, 각각의 while문을 기준으로 상세하게 살펴보겠다.

 

time = [0] * (N + 1)
parent = [[] for _ in range(N + 1)]
queue = deque([(st, 0)])
while queue:
    x, t = queue.popleft()
    for y, _t in roads[x]:
        in_roads[y] -= 1
        next_time = t + _t
        if time[y] == next_time:
            parent[y].append(x)
        if time[y] < next_time:
            time[y] = next_time
            parent[y] = [x]
        if not in_roads[y]:
            queue.append((y, time[y]))

 첫 번째는 경로를 구하기 위하여 위상 정렬을 활용한다.

time : 최대 시간을 구하는데 활용, 리스트에 시간을 더 느리게 갱신하였고

parent : 나중에 도로의 수를 세기 위하여 각 점의 부모 저장

 

이후 while문에서는 인접 도로를 확인하며 위상 정렬을 적용한다.

 

roads_count = set()
queue = deque([end])
while queue:
    x = queue.popleft()
    for y in parent[x]:
        if (y, x) in roads_count:
            continue
        roads_count.add((y, x))
        if y != st:
            queue.append(y)

 도로의 수를 세는 것은 조금은 번거로울 수 있는 작업이다. 나는 set과 BFS를 활용했다.

while문에서 도착지부터 parent에 저장한 부모를 따라가며 탐색, 인접도로를 set에 저장하는 방식으로 해결했다.


3. 생각 정리

 위상 정렬이 아직은 낯설다고 느껴지는 부분도 있고, 위상 정렬 과정에서 생성한 데이터를 또다시 활용하는 형식의 문제를 처음 만나게 되어 문제 해결에 시간이 소모되었다. 위상 정렬을 활용하는 데 있어 쉬운 문제에서는 거의 유사한 방식으로 활용하지만, 조금 난이도가 있는 문제에서의 활용방식이 달라지는 부분을 더 익혀야 될 것 같고, 경로를 역추적하는 경우도 익숙해져야 할 것 같다.

'CS > 알고리즘 & 문제풀이' 카테고리의 다른 글

[Python] 백준 17417 게리맨더링  (0) 2022.09.05
[Python] 백준 20181 꿈틀꿈틀 호석 애벌레  (0) 2022.09.04
[알고리즘] Segment Tree, lazy propagation  (0) 2022.08.19
[Python] 백준 13258 복권 + 은행  (0) 2022.08.05
[Python] 백준 1655 가운데를 말해요  (0) 2022.08.03
'CS/알고리즘 & 문제풀이' 카테고리의 다른 글
  • [Python] 백준 17417 게리맨더링
  • [Python] 백준 20181 꿈틀꿈틀 호석 애벌레
  • [알고리즘] Segment Tree, lazy propagation
  • [Python] 백준 13258 복권 + 은행
mintropy
mintropy
민트로피의 하루하루 오늘보다 더 나은 내일
  • mintropy
    민트로피의 민트초코
    mintropy
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 생각 정리
        • 코딩테스트
        • SSAFY
      • 디지털 노트
        • Obsidian.md
        • Notion
      • CS
        • 알고리즘 & 문제풀이
        • AI
        • DB
        • 디자인패턴
      • Projects
      • Python
        • Python Web Framework
      • JavaScript
        • React.js
      • Docker
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    구현
    브루트포스
    pydantic
    회고
    line
    bfs
    project_zero
    DRF
    SSAFY
    프로그래머스
    union-find
    Combinatorics
    ps
    백준
    DP
    게임이론
    카카오
    fastapi
    조건분기
    web framework
    dfs
    그리디
    Python
    django
    trie
    코딩테스트
    파이썬
    markdown
    알고리즘
    프로젝트
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
mintropy
[Python] 백준 1948 임계경로
상단으로

티스토리툴바