dijkstra-1504
N은 정점 개수다. (1,N)까지의 최단 거리를 구해야 한다. 단, 입력받은 2개의 정점을 꼭 통과해야한다. 만약 최단경로가 없다면 -1을 출력한다.
Solution
fail
최단경로면서, 가중치 값이 양인 것을 보고 다익스트라를 떠올렸다. 이 때, 2개의 정점을 꼭 통과해야 했다. 이에 대한 해결책으로
// A, B : 통과해야 할 2개의 정점
dijkstra(1,N);
if(dist[A] < dist[B]) 최단 거리 경로 : 1-A-B-N
else                                    최단 거리 경로 : 1-B-A-N위와 같이 단순하게 생각했다.
다익스트라로 최단경로 구할 시, 출발지는 0으로 초기화 후, 도착지까지 최단경로를 구한다. 즉, 1-A VS 1-B 에서 A가 더 최단거리일지라도 A-B-N 보다 B-A-N이 더 최단거리일 수 있다.
success
출발지에 따라 사용할 수 있는 간선이 달라지기 때문에 모든 출발지-도착지에 대해 비용을 비교해야한다.
shortestCost = min(dijkstra(1,A) + dijkstra(A,B) + dijkstra(B,N),
        dijkstra(1,B) + dijkstra(B,A) + dijkstra(A,N))fail
위와 비슷한 맥락이다. 최단경로는 출발지(cost=0)에 따라 달라진다. 두번째 경로(ex. A-B)에 대한 최단경로 구할 때, 첫번째 경로(ex. 1-A)의 각 정점에 대한 최단경로(dist[vertex])를 초기화 하지 않았다. 출발지가 달라졌을 때 모든 최단경로가 달라질 것이라고 생각하지 못했다.
이외에도 최단경로를 가진 정점을 먼저 방문하기 위한 우선순위 큐도 초기화해야한다.
#include <iostream>
#include <queue>
#include <vector>
#include <stdio.h>
#include <algorithm>
using namespace std;
typedef long long ll;
class CompareCost{
public:
    bool operator()(pair<int, ll> n1, pair<int, ll> n2){
      return n1.second > n2.second;
    }
};
const int INF = 800001;
vector <pair <int, ll> > edges[801];
priority_queue <int, vector<int>, greater<ll> > mustPass;
bool isVisited[801];
ll dist[801];
int N;
void dijkstra(int start, int dst){
  fill_n(dist, N+1, INF);
  fill_n(isVisited, N+1, false);
  dist[start] = 0;
  priority_queue <pair <int, int>, vector <pair <int, int> >, CompareCost> pq;
  pq.push(make_pair(start, dist[start]));
  while(!pq.empty()){
    int current;
    do {
      current = pq.top().first;
      pq.pop();
    }while(!pq.empty() && isVisited[current]);
    if(current == dst) return;
    isVisited[current] = true;
    for(int i = 0; i<edges[current].size(); i++){
      int to    = edges[current][i].first;
      ll cost   = edges[current][i].second;
      if(dist[to] > dist[current] + cost){
        dist[to] = dist[current] + cost;
        pq.push(make_pair(to, dist[to]));
      }
    }
  }
}
int main() {
  int M, mustPassArr[2];
  ll result1 = 0, result2 = 0;
  scanf("%d %d", &N, &M);
  for(int i = 0; i<M; i++){
    int from, to, cost;
    scanf("%d %d %d", &from, &to, &cost);
    edges[from].push_back(make_pair(to, cost));
    edges[to].push_back(make_pair(from, cost));
  }
  scanf("%d %d", &mustPassArr[0], &mustPassArr[1]);
  for (int i=0; i<2; i++) mustPass.push(mustPassArr[i]);
  dijkstra(1, mustPassArr[0]);
  result1 += dist[mustPassArr[0]];
  dijkstra(mustPassArr[0], mustPassArr[1]);
  result1 += dist[mustPassArr[1]];
  dijkstra(mustPassArr[1], N);
  result1 += dist[N];
  dijkstra(1, mustPassArr[1]);
  result2 += dist[mustPassArr[1]];
  dijkstra(mustPassArr[1], mustPassArr[0]);
  result2 += dist[mustPassArr[0]];
  dijkstra(mustPassArr[0], N);
  result2 += dist[N];
  ll result = min(result1, result2);
  if(result >= INF)printf("-1\n");
  else{
    printf("%lld\n", result);
  }
  return 0;
}Issue
방향성이 없는 그래프가 주어졌다라는 내용을 보고 양방향 그래프라는 걸 떠올렸어야 했는데 그러지 못했다.
Summary
그래프에서 각 정점에 대한 최단경로는 같은 그래프 일지라도 시작점에 따라 달라진다. 따라서, 시작점이 달라질 때마다 각 정점에 대한 최단경로, 최단경로를 가진 정점을 먼저 파악하기 위한 우선순위 큐는 모두 초기화해야한다.
Last updated
Was this helpful?