본문 바로가기
PS - 알고리즘

14077 - Parada

by codeStudyCafe 2024. 12. 2.

번역

더보기

탱크 퍼레이드가 1번 도시에서 $N$번 도시까지 진행됩니다. 각 도로 $i$마다 몇 대의 탱크 $T_i$가 지나갈 수 있는지 알려져 있으며, 이 수를 넘으면 도로를 보수해야 합니다. 이후에는, 도로 수리 비용이 탱크 수에 따라 제곱으로 증가하며, 이는 $C_i*(T-T_i)^2$ 원입니다. 여기서 $C_i$는 도로 수리 비용의 계수입니다. 도로를 복구하는 데 사용할 수 있는 연간 예산 $K$원이 있습니다. $K$원을 넘지 않는 비용으로 얼마나 많은 탱크를 퍼레이드에 사용할 수 있는지 구하세요. 적어도 하나의 경로는 존재할 것이 보장됩니다.

step 1

더보기

퍼레이드에 $X$대의 탱크를 참여시킬 수 있는지 없는지를 구할 수 있다고 해봅시다. $X$대를 참여시킬 수 있을 때 $X-1$대도 참여시킬 수 있으므로 이 문제는 이분 탐색으로 해결할 수 있습니다.

step 2

더보기

퍼레이드에 $X$대의 탱크를 참여시킬 수 있는지 없는지는 다익스트라로 구할 수 있습니다.

코드

더보기
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<set>
#include<vector>
#include<queue>
using namespace std;
vector<pair<long long int, pair<long long int, long long int>>> v[100100];
priority_queue<pair<long long int, long long int>> q;
long long int g[100100];
long long int M = 922337203685470000ll;
int main() {
	long long int n, m, x, i, j;
	scanf("%lld%lld%lld", &n, &m, &x);
	for (i = 1;i <= m;i++) {
		long long int xx, yy, zz, ww;
		scanf("%lld%lld%lld%lld", &xx, &yy, &zz, &ww);
		v[xx].push_back({ yy,{zz,ww} });
		v[yy].push_back({ xx,{zz,ww} });
	}
	long long int s = 0, e = 1000000;
	while (s < e) {
		long long int mi = (s + e) / 2 + 1;
		q.push({ 0,1 });
		for (i = 1;i <= n;i++) {
			g[i] = x+1;
		}
		g[1] = 0;
		while (q.size()) {
			long long int gg = -q.top().first, i = q.top().second;
			q.pop();
			if (gg != g[i]) continue;
			for (j = 0;j < v[i].size();j++) {
				long long int d = v[i][j].first, p = v[i][j].second.first, c = v[i][j].second.second;
				long long int gg = (mi <= c ? 0 : p * (mi - c) * (mi - c));
				if (g[i] + gg < g[d] && g[i] + gg <= x) {
					g[d] = g[i] + gg;
					q.push({ -g[d], d });
				}
			}
		}
		if (g[n] > x) e = mi - 1; else s = mi;
	}
	printf("%lld", s);
	return 0;
}

'PS - 알고리즘' 카테고리의 다른 글

2834 - 박스 정렬  (0) 2024.12.16
28219 - 주유소  (0) 2024.12.09
3057 - 디버그  (0) 2024.11.25
25961 - 스코어보드 보기 귀찮아  (0) 2024.11.18
12877 - 먹이 사슬  (0) 2024.11.11