오늘의 알고리즘

[C++] 백준 9370 미확인도착지

하늘하늘 . 2023. 5. 3. 17:21
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
 
using namespace std;
 
int T, n, m, t, s, g, h;
int a, b, d, temp;
 
set<int> destin; 
int dist_s[2001];
int dist_g[2001];
int dist_h[2001];
vector<pair<int, int>> arr[2001];
 
void dijkstra(int start, int* dist) 
{
	priority_queue <pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pri_que;
	pri_que.push({ 0, start });
	dist[start] = 0;
 
	while (!pri_que.empty()) 
	{
		int cost = pri_que.top().first;
		int now = pri_que.top().second;
		pri_que.pop();
 
		for (int i = 0; i < arr[now].size(); ++i)
		{
			int beforeCost = dist[arr[now][i].first];
			int nextCost = cost + arr[now][i].second;
 
			if (beforeCost > nextCost)
			{
				dist[arr[now][i].first] = nextCost;
				pri_que.push({ nextCost, arr[now][i].first });
			}
		}
	}
}
 
int main() 
{
	cin >> T;
 
	while (T--) 
	{
		cin >> n >> m >> t;
		cin >> s >> g >> h;
 
		destin.clear();
 
		for (int i = 1; i <= 2000; ++i) 
		{
			arr[i].clear();
			dist_s[i] = 2000000001;
			dist_g[i] = 2000000001;
			dist_h[i] = 2000000001;
		}
 
		for (int i = 0; i < m; ++i) 
		{
			cin >> a >> b >> d;
			arr[a].push_back({ b, d });
			arr[b].push_back({ a, d });
		}
 
		for (int i = 0; i < t; ++i) 
		{
			cin >> temp;
			destin.insert(temp);
		}
 
		dijkstra(s, dist_s);
		dijkstra(g, dist_g);
		dijkstra(h, dist_h);
 
		for (int iter : destin)
		{
			if (dist_s[iter] == (dist_s[g] + dist_g[h] + dist_h[iter]))
				cout << iter << ' ';
 
			else if (dist_s[iter] == (dist_s[h] + dist_h[g] + dist_g[iter]))
				cout << iter << ' ';
		}
 
		cout << "\n";
	}
 
	return 0;
}

이 문제는 다익스트라자 알고리즘을 사용해야했습니다.

g-h 라인을 무조건 지나야 하기 때문에 s - g - h - x 가 더 빠른가 s - h - g - x 가 더 빠른가 확인 해야합니다.

그렇기 때문에 s에서 최소 거리, g에서의 최소거리, h에서의 최소거리를 찾습니다.

그후 s -> g + g ->h + h -> x 가 최소거리인지, s-> h + h ->g + g -> x가 최소거리인지 확인합니다.