알고리즘 공부 및 문제 풀이/백준(BOJ)
[boj] 백준 1939 중량제한 (c++) - 다익스트라
yoonjiy
2022. 10. 26. 15:27
[문제]
https://www.acmicpc.net/problem/1939
1939번: 중량제한
첫째 줄에 N, M(1 ≤ M ≤ 100,000)이 주어진다. 다음 M개의 줄에는 다리에 대한 정보를 나타내는 세 정수 A, B(1 ≤ A, B ≤ N), C(1 ≤ C ≤ 1,000,000,000)가 주어진다. 이는 A번 섬과 B번 섬 사이에 중량제한이
www.acmicpc.net
[풀이]
다익스트라 최단 경로를 구하는 방식을 응용해서 풀 수 있었다.
인접 정점에 대한 weight[](원래의 dist[] 배열 역할) 갱신 시, 현재 방문 정점에서 옮길 수 있는 최대 중량보다 더 작은 값이 실제 옮길 수 있는 중량이 됨에 유의해야 한다.
근데 이후에 찾아보니 이분탐색+bfs로 풀이한 코드가 대부분이었다.. 다양한 방식으로 풀 수 있는 문제인 듯 하다!
이 경우 left=0, right=MAX로 저장 후 mid 값에 대해 그래프 탐색이 가능한지 bfs를 돌린 후, 가능하다면 left 값을 mid+1로, 불가능하다면 right 값을 mid-1로 바꾼 후 반복하는 방식이다.
[코드]
1. 다익스트라
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>
#include <cmath>
#define INF 987654321
using namespace std;
int n, m;
int u, v;
int weight[10001];
vector<pair<int, int>> node[10001];
void dijkstra(int s){
weight[s] = 1000000001;
priority_queue<pair<int, int>> q;
q.push({1000000001, s}); //cost, index
while(!q.empty()){
int c = q.top().first;
int curr = q.top().second;
q.pop();
if(weight[curr] > c) continue;
for(int i=0; i<node[curr].size(); i++){
int next = node[curr][i].first;
int cost = min(node[curr][i].second, c);
if(weight[next] < cost) {
weight[next] = cost;
q.push({cost, next});
}
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
for(int i=0; i<m; i++){
int a, b, c;
cin >> a >> b >> c;
node[a].push_back({b, c});
node[b].push_back({a, c});
}
cin >> u >> v; //공장이 있는 섬의 번호
fill(weight, weight+10001, -1);
//u->v 한번에 이동해서 옮길 수 있는 물품들의 중량의 최댓값
dijkstra(u);
cout << weight[v];
}
2. 이분탐색 + bfs
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>
#include <cmath>
#define INF 987654321
using namespace std;
int n, m;
int u, v;
bool visited[10001];
vector<pair<int, int>> node[10001];
bool bfs(int mid){
visited[u] = true;
queue<int> q;
q.push(u);
while(!q.empty()){
int s = q.front();
q.pop();
if(s==v) return true;
for(int i=0; i<node[s].size(); i++){
int next = node[s][i].first;
int weight = node[s][i].second;
if(!visited[next] && weight>=mid){
visited[next] = true;
q.push(next);
}
}
}
return false;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
for(int i=0; i<m; i++){
int a, b, c;
cin >> a >> b >> c;
node[a].push_back({b, c});
node[b].push_back({a, c});
}
cin >> u >> v; //공장이 있는 섬의 번호
int low = 0;
int high = 1000000001;
int mid, ans;
while(low<=high){
memset(visited, false, sizeof(visited));
mid = (low+high)/2;
if(bfs(mid)){
ans = mid;
low = mid+1;
}
else{
high = mid-1;
}
}
cout << ans << "\n";
}