n : 도시의 개수 ( 1 <= n <= 10,000 )
m : 도로의 개수 ( 1 <= m <= 100,000 )
도시들의 연결 정보 (출발 도시 번호, 도착 도시 번호, 도로를 지나는데 걸리는 시간 )
지도를 그리는 사람들의 출발 도시, 도착 도시가 주어진다.
모든 도시는 출발 도시로부터 도달이 가능하고, 모든 도시로부터 도착 도시에 도달 가능하다.
위상 정렬을 이용하여 시작 도시에서 도착 도시까지의 임계 경로를 확인 후,
도착 도시를 기준으로 시작 도시로 되돌아가며 하며 임계 경로에 속하는 도로의 개수를 센다.
임계 경로란?
여러 단계의 과정을 거치는 작업에서 그것을 완성하려면 여러 과정의 경로가 동시에 수행되어야 할 때, 그 중 가장 긴 경로이다. 각 작업의 공정을 그래프 형태로 나타냈을때, 임계 경로는 시작점에서 종료점에 이르는 가장 긴 경로이다.
- 네이버 지식백과 -
import sys
from collections import deque
input = sys.stdin.readline
# n : 도시의 개수, m : 도로의 개수
n = int(input())
m = int(input())
graph = [[] * (n + 1) for _ in range(n + 1)]
back_graph = [[] * (n + 1) for _ in range(n + 1)]
indegree = [0] * (n + 1) # 진입차수
visited = [0] * (n + 1) # 백트래킹시 큐에 중복 삽입 방지
result = [0] * (n + 1) # 각 도시로 이동하는 임계 경로 저장을 위한 변수
# graph[출발 도시] = (도착 도시, 걸리는 시간)
# back_graph[도착 도시] = (출발 도시, 걸리는 시간)
# 진입 차수 초기화
for _ in range(m):
start_city, target_city, weight = map(int, input().split())
graph[start_city].append((target_city, weight))
back_graph[target_city].append((start_city, weight))
indegree[target_city] += 1
start, target = map(int, input().split())
queue = deque()
queue.append(start)
# 위상 정렬
def topology_sort():
while queue:
now = queue.popleft()
for next, weight in graph[now]:
# 현재 도시를 거쳐가느데 걸리는 시간과 이전의 다른 경로의 걸리는 시간을
# 비교하여 큰 값을 임계 경로로 설정
result[next] = max(result[next], result[now] + weight)
indegree[next] -= 1
# 위상 정렬 수행 과정에서 진입차수가 0인 도시 발생시 큐에 삽입
if indegree[next] == 0:
queue.append(next)
# 백트래킹
queue.append(target)
count = 0
while queue:
now = queue.popleft()
for pre, weight in back_graph[now]:
# ( 현재 도시까지의 임계경로 ) 과
# ( 현재 도시에서 인접한 도시까지의 임계 경로 + 현재 도시의 인접 도시에서 현재 도시로 이동하는데 걸리는 시간 )
# 이 같으면 그 인접 도시는 임계 경로의 한 도시이다.
if result[now] == result[pre] + weight:
count += 1
# 임계 경로의 도로 중복 카운트 방지
if visited[pre] == 0:
queue.append(pre)
visited[pre] = 1
# 결과 출력
print(result[target])
print(count)
topology_sort()