[백준] 1800번: 인터넷 설치 C++ - 다익스트라가 메인 로직이 아닐 수 있다. 결정 문제의 비밀을 알려드립니다. 💀💀☠️☠️😎
2025. 10. 20. 16:58ㆍ알고리즘/문제풀이
https://www.acmicpc.net/problem/1800
문제를 분석해보면
1. 다익스트라로 1->N까지의 경로는 구할 수 있다.
2. 하지만 그 경로가 정답인지 확정할 수 없다.
3. 문제는 "최대 비용을 최소화" 하라는 최적화 문제이다.
최적화 문제의 변수를 "mid"라 하자. 답을 저장할 변수를 mid라 하는 것이다.
원래의 문제는 1->N 경로 중 최대 요금이 가장 작은 mid를 찾는 것이다.
이를 결정 문제로 변경하면 1->N 경로 중 최대 요금을 mid 이하로 만들 수 있을까? 가 된다.
- mid로 경로를 경로를 만들었는데 해당 경로의 요금이 mid 초과인 수를 셌을 때 K 초과라면?
- mid로는 답을 낼 수 없다. 현재 mid 보다 더 큰 요금을 상한선으로 잡아야 한다.
- 반대라면 현재의 mid도 가능하고 더 적어도 된다.
- 현재의 mid로 경로를 구할 때 다익스트라를 변경하면 된다. 요금이 mid 이상이면 weight를 1, 아니라면 0으로 두는 것이다. 그리고 다익스트라를 때려서 최종 경로의 weight가 K 초과인지만 판단하면 된다.
마지막으로 파라미터릭 서치를 적용해도 되는 것인지 단조성을 증명해보자.
- 최대 요금이 100원 일 때 연결이 된다면 101원도 가능하다.
- 100원 일 때 불가능하다면 49원은 불가능하다.
- 단조성이 증명되었다!
/** **/
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>
using namespace std;
int n, p, k, ans = -1;
vector<pair<int, int>> adj[1002];
int func(int mid)
{
// mid보다 크면 weight를 1로 생각
vector<int> dist(n + 1, 0x7f7f7f7f);
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
dist[1] = 0;
pq.push({0, 1});
while (!pq.empty())
{
auto cur = pq.top();
pq.pop();
// dist[cur.second]와 우선순위 큐의 정점이 다른 경우
if (dist[cur.second] < cur.first)
continue;
for (auto nxt : adj[cur.second])
{
int nxt_cost = cur.first + (nxt.first > mid);
if (dist[nxt.second] > nxt_cost)
{
// 갱신
dist[nxt.second] = nxt_cost;
pq.push({nxt_cost, nxt.second});
}
}
}
return dist[n];
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cin >> n >> p >> k;
for (int i = 0; i < p; i++)
{
int u, v, w;
cin >> u >> v >> w;
adj[u].push_back({w, v});
adj[v].push_back({w, u});
}
int left = 0, right = 1000000;
while (left < right)
{
int mid = (left + right) / 2;
if (func(mid) <= k)
{
ans = mid;
right = mid;
}
else
{
left = mid + 1;
}
}
cout << ans;
}
/*
1~N번 연결
K개의 선은 공짜
나머지 선 중 가장 비싼 것을 구하기.
다익스트라 -> ElogE. E=10000
K개의 선이 공짜라서 단순 다익스트라로는 불가능함.
결정 문제로 바꿔서 남은 것 중 최대 비용을 mid로 한다면 연결이 가능한가?를 보면 된다.
1~n까지를 연결해서 mid 초과인 간선을 셌을 때 K 이상이라면?
-> mid는 현재보다 크다.
아니라면 mid는 현재보다 작다.
경로를 구하는 것은. 케이블 비용이 mid 보다 크다면 가중치를 1로 두고, 아니라면 0으로 둬서 다익스트라로 구할 수 있다.
*/'알고리즘 > 문제풀이' 카테고리의 다른 글
| [백준] 15732번: 도토리 숨기기 - 왜 이분탐색인가? (0) | 2025.10.16 |
|---|---|
| [백준] C++ 풀이 22866번: 탑 보기 - 이게 스택이라고?? (1) | 2025.09.08 |
| [백준] 2473: 세 용액 C++ 풀이 - 굉장히 어려운 이분탐색 (0) | 2025.03.22 |
| [백준] 2467: 용액, 3151: 합이 0 - 이분 탐색을 활용한 숫자의 합을 0으로 만들기 (0) | 2025.03.21 |
| [백준] C++ 5904: Moo 게임 - 굉장히 큰 수에 대한 재귀 (0) | 2024.11.17 |