791 words
4 minutes
[BOJ] 미확인 도착지
TimeLimit | MemoryLimit | Condition | TAG |
---|---|---|---|
3s | 256MB | 1 ≤ T ≤ 100 2 ≤ N ≤ 2000 1 ≤ M ≤ 50,000 1 ≤ t ≤ 100 1 ≤ s,g,h ≤ N, g ≠ h 1 ≤ a < b ≤ N 1 ≤ d ≤ 1000 | Dijkstra |
문제를 잘 읽으면 전혀 어려울 것이 없는 문제였습니다. 문제에서 말하는 바를 정확히 이해하면 다익스트라 딸깍 딸깍으로 풀 수 있는데.. 그걸 알아내는데 20분을 날렸답니다 ㅎ하핳
가는 start에서 g - h, h - g를 거치지 않고 가는 경로가 있더라도 지나가도 괜찮구요..
그래서 그냥 start에서의 모든 최단 경로, g에서의 모든 최단 경로, h에서의 모든 최단 경로를 구하고
start에서 g로 가는 cost와 g에서 h로 가는 cost 그리고 h에서 target까지 가는 cost를 더해서 start 최단 경로랑 겹치면 그게 답이다. 이런식으로 답을 도출할 수 있습니다..
결국은
if(start[g] + gn[h] + hn[target] == start[target] ||
start[h] + hn[g] + gn[target] == start[target])
그냥 이거 도출하면 띡하고 나오는.. 문제 ㅠㅜ
정답 코드
중간에 깨달았다고 뻘짓해서 ㅠㅜ 더 걸렸슴둥..
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <sstream>
#include <iomanip>
#include <string>
#include <numeric>
#include <unordered_set>
#include <unordered_map>
#include <climits>
using namespace std;
using ll = long long;
vector<ll> finder(int start, vector<vector<pair<int, int>>>& graph, int n){
vector<ll> visited(n+1);
for(int i = 1; i < n+1; i++) visited[i] = LLONG_MAX;
priority_queue<pair<int,int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
visited[start] = 0;
q.push({0, start});
while(!q.empty()){
auto [cost, idx] = q.top(); q.pop();
for(int i = 0; i < graph[idx].size(); i++){
auto [next, distance] = graph[idx][i];
if(visited[next] <= distance + cost) continue;
visited[next] = distance + cost;
q.push({distance + cost, next});
}
}
return visited;
}
void solution(){
int n, m, t;
int s, g, h; // 타겟들이 시작한 위치 = s, g랑 h를 이어주는 edge를 지남. 즉, 다시는 여기 방문할 일이 없다 이거임.
cin >> n >> m >> t;
cin >> s >> g >> h;
vector<vector<pair<int, int>>> graph(n+1);// idx, cost
// vector<pair<int, int> > graph[n+1];// idx, cost
// 이거 중복 처리가 필요없음. "교차로 사이에는 도로가 많아봐야 1개이다"
vector<int> targets(t);
for(int i = 0; i < m; i++){
int a, b, c;
cin >> a >> b >> c;
graph[a].push_back({b, c});
graph[b].push_back({a, c});
}
for(int i = 0; i < t; i++) cin >> targets[i];
// 이거는 어떻게 생각하면 되냐면, g랑 h를 둘 다 다익스트라를 돌려서 그냥 후보들 중에서 가까운 놈 고르면 됨.
// 왜냐면 결국 제일 빠른 길로 가려고는데 왜 멀어지는 길을 택한 것이냐.. 이것도 문제여서
// 아 근데 이거는 3번 돌려야됨. 왜냐면 시작 위치부터 다 돌려야되는데, 그래서 시작 위치에서 먼 더 코스트가 먼 친구를 골라야되는 것였다.. 아 알았네요.. 이상하게 들어갈 뻔..
// 아 그냥 3개 구해서 하면 되는거였네..
vector<ll> start = finder(s, graph, n);
vector<ll> gn = finder(g, graph, n);
vector<ll> hn = finder(h, graph, n);
vector<int> result;
for(int target : targets){
if(start[g] + gn[h] + hn[target] == start[target] ||
start[h] + hn[g] + gn[target] == start[target]) result.push_back(target);
}
sort(result.begin(), result.end());
for(int ans : result) cout << ans << " ";
}
int main(){
ios_base::sync_with_stdio(0);
cin.tie(0);
int t;
cin >> t;
while(t --> 0){
solution();
cout << "\n";
}
return 0;
}
[BOJ] 미확인 도착지
https://compy07.github.io/Blog/posts/boj/9370/