풀이

[백준] 5719 - 거의 최단 경로 (c++)

땅왕 2025. 1. 12. 14:04

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

 

문제 요약

방향 그래프가 주어진다. 시작점과 도착점이 주어질 때 모든 최단 경로에 속하는 간선을 하나도 사용하지 않은 경로 중 최단경로의 길이를 구해라. 

 

풀이 (MlogN)

  • 다익스트라

다익스트라를 한 번 돌리면서 한 정점에 대해 최단경로로 도달할 수 있는 전 정점들을 연결하는 그래프를 구성해준다. 보통 다익스트라는 새로운 비용이 원래 비용보다 작을 때만 pq에 추가해주는데 같을 때도 추가해주면 된다. vis배열을 만들어 한 정점 대해 업데이트는 한 번만 되게 한다. 

그렇게 구성한 그래프에서 d부터 s까지 역추적 해가며 포함되는 간선을 모두 지우면 s->d 최단경로의 속하는 간선을 모두 지울 수 있다.

다익스트라 한 번 더 돌려주면 끝

#include <bits/stdc++.h>
using namespace std;
#define ll long long

int main() {
    cin.tie(0)->sync_with_stdio(0);
    while(1) {
        int n,m,s,t;
        cin>>n>>m;
        if(n==0)
            break;
        cin>>s>>t;
        vector<vector<int>> adj(n,vector<int>(n));
        for(int i=0,u,v,c;i<m;i++)
            cin>>u>>v>>c,adj[u][v]=c;
        vector<bool> vis(n);
        priority_queue<array<int,3>,vector<array<int,3>>,greater<array<int,3>>> pq;
        vector<int> dis(n,1e9);
        vector<vector<int>> in(n);
        pq.push({dis[s]=0,s,s});
        while(pq.size()) {
            auto[cc,u,p]=pq.top();pq.pop();
            if(cc>dis[u])continue;
            in[u].push_back(p);
            if(vis[u])continue;
            vis[u]=1;
            for(int v=0;v<n;v++) {
                int c;
                if(!(c=adj[u][v]))continue;
                if(cc+c<=dis[v])
                    pq.push({dis[v]=cc+c,v,u});
            }
        }
        fill(vis.begin(),vis.end(),0);
        queue<int> q;
        q.push(t);
        while(q.size()) {
            int u=q.front();q.pop();
            for(int v:in[u]) {   
                adj[v][u]=0;
                if(!vis[v])
                    q.push(v),vis[v]=1;
            }
        }
        fill(dis.begin(),dis.end(),1e9);
        pq.push({dis[s]=0,s,0});
        while(pq.size()) {
            auto[cc,u,p]=pq.top();pq.pop();
            if(cc>dis[u])continue;
            for(int v=0;v<n;v++) {
                int c;
                if(!(c=adj[u][v]))continue;
                if(cc+c<dis[v])
                    pq.push({dis[v]=cc+c,v,u});
            }
        }
        cout<<(dis[t]==1e9?-1:dis[t])<<'\n';
    }
}