백준: Class 6 - 1948(DAG에서 최장경로)

1 분 소요


</br> DAG(Directed Acyclic Graph)는 사이클이 없는 방향 그래프다.
원래 최장경로 구하기는 NP문제지만, DAG에서는 위상 정렬로 구할 수 있다.
시작점에서 다음 점까지 최대의 시간이 걸리는 것을 고르는 것이기 때문이다.
</br>

1948: 임계경로

https://www.acmicpc.net/problem/1948

#include <bits/stdc++.h>
#define P pair<int, int>

using namespace std;

vector<P> graph[10001];
vector<P> revgraph[10001];
int ind[10001];
int times[10001];

int main(){
    ios::sync_with_stdio(false);
    cin.tie(NULL);

    int n, m;
    cin >> n >> m;
    for(int i = 0; i < m; i++){
        int a, b, c;
        cin >> a >> b >> c;
        graph[a].push_back(make_pair(c, b));
        revgraph[b].push_back(make_pair(c, a));
        ind[b]++;
    }
    int start, arrival;
    cin >> start >> arrival;

    queue<int> q;
    q.push(start);
    while( q.size() ){
        int now = q.front();
        q.pop();
        for(int j = 0; j < graph[now].size() ; j++){
            int c = graph[now][j].first;
            int nx = graph[now][j].second;
            ind[nx]--;
            times[nx] = max(times[nx], times[now] + c);
            if( ind[nx] == 0 ) q.push(nx);
        }
    }
    cout << times[arrival] << '\n';

    q.push(arrival);
    ind[arrival] = 1;
    int cnt = 0;
    while( q.size() ){
        int now = q.front();
        q.pop();

        if( now == start ) break;

        for(int j = 0; j < revgraph[now].size() ; j++){
            int c = revgraph[now][j].first;
            int nx = revgraph[now][j].second;
            if( times[now] - c == times[nx] ){
                cnt++;
                if( ind[nx] == 0 ){
                    ind[nx] = 1;
                    q.push(nx);
                }
            }
        }
    }
    cout << cnt << '\n';

}

얘는 일단 위상 정렬로 최장 경로의 시간은 구했는데, 그 경로들을 다시 탐색도 해야 한다.
따라서 방향이 반대인 그래프에서 도착->시작으로 탐색을 진행하며, 현재 times[now] - c == times[nx]라면 이 길이 최장 경로이므로 이 쪽으로 탐색을 진행한다.
</br>


요새 거들 비하면 간단한 편이라 좋다
</br>

댓글남기기