https://www.acmicpc.net/problem/2307
2307번: 도로검문
그림 1은 어떤 도시의 주요 지점과 그 지점들 간의 이동시간을 나타낸 그래프이다. 그래프의 노드는 주요 지점을 나타내고 두 지점을 연결한 도로(에지)에 표시된 수는 그 도로로 이동할 때 걸
www.acmicpc.net
이 문제에서 모든 M개의 간선에 대해 제외하고 다익스트라를 돌리게 되면, O(MNlogM) -> TLE가 날 수 있다.
따라서 시간 최적화를 진행해야 한다.
잘 생각해 보면, 용의자가 1번 정점에서 n번 정점까지 가는 데에 쓰인 간선 중에서만 검문을 거치면 된다. 그 외 간선에서는 검문을 해봤자, 최단 거리에 영향을 주지 않기 때문이다.
그렇다면 최단 거리에 쓰인 간선을 어떻게 판단할 수 있을까?
본인은 parent 배열을 이용해 최단 거리가 갱신될 때 node, nextNode를 이용해서 parent[nextNode] = node 이런 식으로 다음 정점을 가리켜 주었다.
그래서 parent[n] 부터, parent[x] = 1까지 간선을 제외해 다익스트라를 돌렸다.
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
int n, m, ok;
vector<vector<pair<int, int>>> v;
int parent[1001];
int dijk(int a, int b)
{
vector<int> dis(n + 1, 987654321);
priority_queue<pair<int, int>> pq;
dis[1] = 0;
pq.push({0, 1});
while (!pq.empty())
{
int node = pq.top().second;
int cost = -pq.top().first;
pq.pop();
if (dis[node] < cost)
continue;
for (auto &i : v[node])
{
if (ok && ((node == a && i.first == b) || (node == b && i.first == a)))
{
continue;
}
int nxNode = i.first;
int nxCost = cost + i.second;
if (dis[nxNode] > nxCost)
{
if (!ok)
{
parent[nxNode] = node;
}
pq.push({-nxCost, nxNode});
dis[nxNode] = nxCost;
}
}
}
ok = 1;
if (dis[n] == 987654321)
{
return -1;
}
return dis[n];
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m;
v.resize(n + 1);
for (int i = 0; i < m; i++)
{
int a, b, c;
cin >> a >> b >> c;
v[a].push_back({b, c});
v[b].push_back({a, c});
}
int dis = dijk(-1, -1);
int ans = -1;
for (int i = n; i != parent[i]; i = parent[i])
{
int t = dijk(i, parent[i]);
if (t == -1)
{
ans = -1;
break;
}
ans = max(ans, t - dis);
}
cout << ans;
}
'ps' 카테고리의 다른 글
[백준] 2022 - 사다리 (0) | 2023.02.14 |
---|---|
[백준] 2982 - 국왕의 방문 (0) | 2023.01.22 |
[백준] 4315 - 나무 위의 구슬 (0) | 2023.01.17 |
[백준] 17831 - 대기업 승범이네 (0) | 2023.01.16 |
[백준] 1749 - 점수따먹기 (0) | 2023.01.16 |
댓글