https://www.acmicpc.net/problem/1800
1800번: 인터넷 설치
첫 번째 줄에 N(1 ≤ N ≤ 1,000), 케이블선의 개수 P(1 ≤ P ≤ 10,000), 공짜로 제공하는 케이블선의 개수 K(0 ≤ K < N)이 주어진다. 다음 P개의 줄에는 케이블이 연결하는 두 컴퓨터 번호와 그 가격이 차
www.acmicpc.net
1. 접근
다익스트라 + 경로저장으로 풀 수 있을 줄 알았다.
하지만 구하려는 값이 최단 경로의 최소비용이 아닌 모든 경우의 최소비용이기 때문에 틀린 방식이었다.
2. 풀이
결국 검색으로 힌트를 얻고 풀 수 있었다
이분 탐색 + 다익스트라로 푸는 것인데, 이분 탐색으로 비용 상한선을 설정한 뒤, 다익스트라에 적용한다
이 때, K개 연결에 대해서는 무료인 조건을 활용하기 위해
d[n]에 일반적으로 저장했던 누적비용이 아닌, 비용 상한선이 넘는 값을 카운트 해준다. 이걸 구현하는게 포인트
최소비용 값은 이분 탐색 시 사용하는 중간값(m)으로 기록 가능하기에 가능하다
나중에 한번 더 풀어봐야할 문제
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
struct comp {
bool operator()(pair<int,int> a, pair<int,int> b) {
return a.second > b.second;
}
};
int N, P, K;
int a, b, c;
int s, e, m;
vector<vector<pair<int, int>>> v;
priority_queue<pair<int, int>, vector<pair<int, int>>, comp> pq;
int d[1001];
int res = -1;
bool dijkstra(int upper) {
for (int i = 1; i <= N; i++)
d[i] = INT_MAX;
pq.push({ 1,0 });
d[1] = 0;
while (!pq.empty()) {
int src = pq.top().first, cost = pq.top().second;
pq.pop();
if (d[src] < cost)
continue;
for (int i = 0; i < v[src].size(); i++) {
int dest = v[src][i].first, totCost = cost + (v[src][i].second > upper); // 비용상한선을 넘는다면 카운팅
if (d[dest] > totCost) {
d[dest] = totCost;
pq.push({ dest, totCost });
}
}
}
return d[N] <= K;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> N >> P >> K;
v.resize(N + 1);
s = 0, e = P - 1;
for (int i = 0; i < P; i++) {
cin >> a >> b >> c;
v[a].push_back({ b,c });
v[b].push_back({ a,c });
e = max(e, c);
}
while (s <= e) {
m = (s + e) / 2;
if (dijkstra(m)) {
res = m;
e = m - 1;
}
else {
s = m + 1;
}
}
cout << res;
return 0;
}
'알고리즘 > 알고리즘' 카테고리의 다른 글
[C++] 백준 20058번 : 마법사 상어와 파이어스톰 (0) | 2021.10.09 |
---|---|
[C++] 백준 10159번 : 저울 (0) | 2021.09.10 |
[C++]백준 1197번 : 최소 스패닝 트리 (0) | 2021.09.09 |
[C++]백준 8972번 : 미친 아두이노 (0) | 2021.09.04 |
[C++]백준 2234번 : 성곽 (0) | 2021.09.03 |