Problem Solving/BOJ(백준)

[BOJ]백준 20160번: 야쿠르트 아줌마 야쿠르트 주세요(C++)/Dijkstra

이진2 2021. 8. 9. 08:00

https://www.acmicpc.net/problem/20160

 

20160번: 야쿠르트 아줌마 야쿠르트 주세요

첫 줄에는 정점의 개수 V(1 ≤ V ≤ 10,000)와 도로의 개수 E(0 ≤ E ≤ 100,000)가 정수로 주어진다. 그 다음 E 줄에 걸쳐 각 도로를 나타내는 세 개의 정수 (u, v, w)가 순서대로 주어진다. 이는 u 와 v(1 ≤

www.acmicpc.net

값의 범위를 신경써야 하는 다익스트라 문제

정점은 10000개라서 인접행렬을 만들 시 10000*10000=1억개 * 4byte의 메모리가 필요한데

간선이 최대 10만개 들어오므로 꼭 인접리스트로 처리해야 한다

#include <cstdio>
#include <vector>
#include <queue>
#define ull unsigned long long
#define pii pair<ull,int>
#define INF 1000000001
using namespace std;

int V, E, M;
vector<int> W(10);
vector<vector<pii>> g;
vector<vector<ull>> dist;

ull dijkstra(int S, int F) {
	if (!dist[S].empty())return dist[S][F];

	dist[S] = vector<ull>(V + 1, INF);
	priority_queue<pii, vector<pii>, greater<>> pq;

	dist[S][S] = 0;
	pq.push(make_pair(0, S));

	while (!pq.empty()) {
		int cur = pq.top().second; 
		int cost = pq.top().first; pq.pop();
		if (cost > dist[S][cur])continue;

		for (auto x : g[cur])
			if (dist[S][x.second] > x.first + dist[S][cur]) {
				dist[S][x.second] = x.first + dist[S][cur];
				pq.push(make_pair(dist[S][x.second], x.second));
			}
	}
	return dist[S][F];
}

int main() {
	scanf("%d%d", &V, &E);
	g = vector<vector<pii>>(V + 1);
	dist = vector<vector<ull>>(V + 1);

	for (int i = 0, u, v, w; i < E; i++) {
		scanf("%d%d%d", &u, &v, &w);
		g[u].push_back(make_pair(w, v));
		g[v].push_back(make_pair(w, u));
	}

	for (int i = 0; i < 10; i++)scanf("%d", &W[i]);
	scanf("%d", &M);

	ull sum = 0;
	int cur = W[0], ans = V + 1;
	for (int i = 0; i < 10; i++) {
		ull d = dijkstra(cur, W[i]);
		if (d == INF)continue;

		sum += d;
		if (dijkstra(M, W[i]) <= sum) {
			ans = W[i] < ans ? W[i] : ans;
		}
		cur = W[i];
	}
	printf("%d", ans == V + 1 ? -1 : ans);
	return 0;
}