💡 PS
[BOJ] 1948 임계경로
date
May 13, 2022
slug
boj-1948
author
status
Public
tags
PS
summary
임계경로 문제에 대한 풀이입니다.
type
Post
thumbnail
category
💡 PS
updatedAt
Aug 3, 2023 09:26 AM
언어
문제
풀이
만나는 시간을 구하는 방법은 BOJ 2611 자동차 경주와 같다.
이 문제에서 추가로 생각해봐야 하는 것은 해당 경로가 유일하지 않을 수 있다는 것이다.
나는 자동차 경주 문제를 풀고 이 문제를 풀었어서 비슷한 로직으로 생각을 했다.
다만 추가로 고려해 준 것은 문제 조건을 만족하는 경로가 여러개 일 수도 있다는 것!
따라서 나는
ans
(ans[i]
= i노드 전에 최대 비용으로 방문한 노드)를 단순히 배열이 아닌 벡터로 선언했다.참고로
cost[i]
는 i
노드 까지 가는데 드는 최대 비용을 의미한다.문제 풀이를 간단히 해보자면,
st
는 시작점이고 en
은 도착점이다.우선 벡터
v
에 도로 정보를 저장한다. 그리고 진입차수를 나타내주는 배열인 inDegree
도 바로 반영해준다.go
는 topological sort
를 해주는 코드이다. 시작점 st
를 먼저 큐에 넣어준다.사이클은 없으므로
n
번 반복해주는 반복문 안에서 가장 먼저 들어온 노드를 t
에 저장하고 pop
한다.노드
t
에서 다음으로 갈 노드들 j
를 반복문을 통해 확인해준다.만약
cost[도착노드]
가 cost[출발노드]+비용(시간)
보다 작다면 ans[도착노드]
를 비워주고 ans[도착노드]
에 새 노드 t
를 넣어준다.두 값이 같다면 그냥
ans[도착노드]
에 새 노드 t
를 넣어준다.(같은 비용을 가진 경로가 여러개인 경우다.)cost[도착노드]
에 값을 갱신시켜주고 진입차수가 0
이라면 큐에 push
해준다.그 다음
chk
에서 재귀함수를 이용하여 비용이 최대인 경로 상에 있는 모든 간선의 수(toatal
)를 구해주었다.중복 계산을 막기 위해 해당 노드 방문 여부인
vis
배열로 체크해 주었다.코드
#include <cstdio> #include <algorithm> #include <queue> using namespace std; struct info { int e, cost; }; int n, m, st, en, total = 0; int inDegree[10000]; int cost[10000]; vector<int> ans[10000]; int vis[10000]; vector<info> v[10000]; void go() { queue<int> q; q.push(st); for(int i = 0; i < n; i++) { int t = q.front(); q.pop(); for(auto j : v[t]) { if (cost[j.e] < cost[t] + j.cost) { ans[j.e].clear(); ans[j.e].push_back(t); } else if (cost[j.e] == cost[t] + j.cost) ans[j.e].push_back(t); cost[j.e] = max(cost[j.e], cost[t] + j.cost); if (--inDegree[j.e] == 0) q.push(j.e); } } } void chk(int t) { if (vis[t]) return; vis[t] = 1; for(int i : ans[t]) { total++; chk(i); } } int main() { scanf("%d %d", &n, &m); for(int a, b, c, i = 0; i < m; i++) { scanf("%d %d %d", &a, &b, &c); a--; b--; v[a].push_back({b,c}); inDegree[b]++; } scanf("%d %d", &st, &en); st--; en--; go(); chk(en); printf("%d\n%d", cost[en], total); }