※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 23975번 문제인 정훈이는 민트초코맛 짜장라면이 먹고 싶다이다.

문제는 아래 링크를 확인하자.

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

 

23975번: 정훈이는 민트초코맛 짜장라면이 먹고 싶다

첫 줄에 N, M, K가 공백으로 구분되어 주어진다. (1 ≤ N, M, K ≤ 1,000,000) 둘째 줄에 각 편의점에 남아있는 민트초코맛 짜장라면의 개수 Ai가 주어진다. (0 ≤ Ai ≤ 100) 셋째 줄부터 M+2번째 줄까지

www.acmicpc.net

먼저, 각 노드가 주어졌을 때 1번 노드로 돌아가는 경로는 한 가지로 고정된다는 점에 주목하자. 각 길의 거리와 편의점의 규모가 변하지 않기 때문이다.따라서, 편의점의 규모 조건에 유의하여 다익스트라(dijkstra) 알고리즘을 통해 각 노드가 주어졌을 때 집으로 돌아가는 길에 들리게 될 다음 노드를 구할 수 있다.

 

이 정보들로 1번 노드를 루트로 하고 나머지 각 노드는 최단거리로 1번 노드로 갈 때 다음으로 방문하게 될 노드를 자신의 부모노드로 갖는 형태의 트리를 생각할 수 있다.

 

이제 이 트리에서, 각 노드가 가리키는 편의점에 재고가 남아있다면 그 재고를 사고, 그렇지 않다면 다음에 이 노드를 경유할 필요가 없다는 점을 기억하면서 쿼리를 처리하는 것으로 문제를 해결할 수 있다. 이는 disjoint set의 구현을 응용하여 간단히 구현할 수 있다.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

int cnt[1000001];
int dist[1000001]; // 1번 노드와의 거리
int visited[1000001];
int parent[1000001];
vector<pair<int, int>> G[1000001]; // {node, 두 노드사이 거리}

int findf(int current) {
	if (cnt[current]) {
		cnt[current]--;
		return current;
	}
	return parent[current] = findf(parent[current]);
}

priority_queue<pair<pair<int, int>,int>> pq; // {{-dist, 노드번호},부모}
void dijkstra() {
	pq.push(make_pair(make_pair(0, 1), 0));
	while (!pq.empty()) {
		int current = pq.top().first.second, d = pq.top().first.first, p = pq.top().second; pq.pop();
		if (visited[current]) continue;
		dist[current] = -d;
		parent[current] = p;
		visited[current] = 1;
		for (auto node : G[current]) {
			int n = node.first, nd = node.second;
			pq.push(make_pair(make_pair(d - nd, n), current));
		}
	}
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	int N, M, K; cin >> N >> M >> K;
	cnt[0] = 1000000007;
	for (int i = 1; i <= N; i++) cin >> cnt[i];
	while (M--) {
		int x, y, d; cin >> x >> y >> d;
		G[x].emplace_back(make_pair(y, d));
		G[y].emplace_back(make_pair(x, d));
	}
	
	dijkstra();

	while (K--) {
		int x; cin >> x;
		if (x > 1 && dist[x] == 0) cout << -1 << '\n';
		else {
			int ans = findf(x);
			if (ans) cout << ans << '\n';
			else cout << -1 << '\n';
		}
	}
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 23974 // C++] 짝수 게임  (0) 2022.01.27
[BOJ 23255 // C++] 구름다리 2  (0) 2022.01.26
[BOJ 7677 // C++] Fibonacci  (0) 2022.01.24
[BOJ 7490 // C++] 0 만들기  (0) 2022.01.23
[BOJ 23893 // C++] 알프스의 힘  (0) 2022.01.22

+ Recent posts