백준 1504 - 특정한 최단 경로
2 minute read
문제링크
문제설명
- 방향성이 없는 그래프가 주어진다. 세준이는 1번 정점에서 N번 정점으로 최단 거리로 이동하려고 한다. 또한 세준이는 두 가지 조건을 만족하면서 이동하는 특정한 최단 경로를 구하고 싶은데, 그것은 바로 임의로 주어진 두 정점은 반드시 통과해야 한다는 것이다.
- 세준이는 한번 이동했던 정점은 물론, 한번 이동했던 간선도 다시 이동할 수 있다. 하지만 반드시 최단 경로로 이동해야 한다는 사실에 주의하라. 1번 정점에서 N번 정점으로 이동할 때, 주어진 두 정점을 반드시 거치면서 최단 경로로 이동하는 프로그램을 작성하시오.
문제접근
- 다익스트라 알고리즘 을 v1, v2 를 시작지점으로 모든 정점에 도달하는 최소 비용을 계산한다.
- 1번 정점에서 출발하여 v1, v2 를 거쳐 N번 정점에 도달하는 경우의 수는 다음과 같다.
- 1 -> v1 -> v2 -> N
- 1 -> v2 -> v1 -> N
- 1 -> v1 -> v2 -> v1 -> N
- 1 -> v2 -> v1 -> v2 -> N
- v1 -> N, v2 -> N 비용에 따라 이미 방문했던 v1 혹은 v2 를 재방문한 후 N번 정점에 도달하는 것이 최소비용이 되는 경우가 있다.
구현
#include <iostream>
#include <vector>
#include <queue>
#include <climits>
#include <algorithm>
#define MAX_E 200000
#define MAX_N 800
using namespace std;
int N, E;
int v1, v2;
int costInfo[2][3]; // costInfo[0] 은 v1에서 1, v2, N 으로 갈 때 필요한 최소비용을 의미
int cand[4];
bool bOne_V1 = true, bV1_V2 = true, bV2_N = true, bOne_V2 = true, bV1_N = true;
vector<pair<int, int>> graph[MAX_E];
void Dijkstra(int start)
{
int sIdx;
if (start == 0) sIdx = v1;
if (start == 1) sIdx = v2;
vector<int> dist(N + 1, INT_MAX);
dist[sIdx] = 0;
queue<pair<int, int>> q;
q.push(make_pair(0, sIdx));
while (!q.empty())
{
int u = q.front().second;
int cost = q.front().first;
q.pop();
if (dist[u] < cost) continue;
for (int i = 0; i < graph[u].size(); i++)
{
int v = graph[u][i].second;
int x = graph[u][i].first;
if (cost + x < dist[v])
{
dist[v] = cost + x;
q.push(make_pair(cost + x, v));
}
}
}
costInfo[start][0] = dist[1];
costInfo[start][2] = dist[N];
if (sIdx == v1) costInfo[start][1] = dist[v2];
else if (sIdx == v2) costInfo[start][1] = dist[v1];
// update status
if (start == 0)
{
if (costInfo[start][0] == INT_MAX) bOne_V1 = false;
if (costInfo[start][1] == INT_MAX) bV1_V2 = false;
if (costInfo[start][2] == INT_MAX) bV1_N = false;
}
else if (start == 1)
{
if (costInfo[start][0] == INT_MAX) bOne_V2 = false;
if (costInfo[start][2] == INT_MAX) bV2_N = false;
}
}
void UpdateCandCost()
{
if (bOne_V1 && bV1_V2 && bV2_N)
{
// 1 -> v1 -> v2 -> N
cand[0] = costInfo[0][0] + costInfo[0][1] + costInfo[1][2];
// 1 -> v1 -> v2 -> v1 -> N
cand[1] = costInfo[0][0] + 2 * costInfo[0][1] + costInfo[0][2];
}
else
{
cand[0] = INT_MAX;
cand[1] = INT_MAX;
}
if (bOne_V2 && bV1_V2 && bV1_N)
{
// 1 -> v2 -> v1 -> N
cand[2] = costInfo[1][0] + costInfo[1][1] + costInfo[0][2];
// 1 -> v2 -> v1 -> v2 -> N
cand[3] = costInfo[1][0] + 2 * costInfo[1][1] + costInfo[1][2];
}
else
{
cand[2] = INT_MAX;
cand[3] = INT_MAX;
}
}
int main()
{
cin.tie(NULL);
ios_base::sync_with_stdio(false);
cin >> N >> E;
for (int i = 0; i < E; i++)
{
int from, to, weight;
cin >> from >> to >> weight;
graph[from].push_back(make_pair(weight, to));
graph[to].push_back(make_pair(weight, from));
}
cin >> v1 >> v2;
Dijkstra(0); // v1
Dijkstra(1); // v2
UpdateCandCost();
int ans = INT_MAX;
for (int i = 0; i < 4; i++)
{
if (cand[i] == INT_MAX) continue;
ans = min(cand[i], ans);
}
if (ans == INT_MAX) cout << "-1\n";
else cout << ans << endl;
}
Leave a comment