본문 바로가기
백준

백준 9370 미확인 도착지

by 콩순이냉장고 2021. 2. 15.

문제 URL : www.acmicpc.net/problem/9370

 

9370번: 미확인 도착지

(취익)B100 요원, 요란한 옷차림을 한 서커스 예술가 한 쌍이 한 도시의 거리들을 이동하고 있다. 너의 임무는 그들이 어디로 가고 있는지 알아내는 것이다. 우리가 알아낸 것은 그들이 s지점에서

www.acmicpc.net

문제접근법 : 

문제에 나와있는대로 s에서 시작해서 g 와 h 또는 h 와 g라는 경로를 건너서 목적지 후보에 도달해야한다.

문제는 다익스트라를 이용해야하지만 어떻게 s에서 출발해서 g,h를 건넌후에 목적지 후보에 도달할수있을까??

 

다익스트라를 이용해서 s점에서 시작해서 t까지의 최단경로를 G(s,t)라고 가정하겠다.

 

주어진 사진에서 G(2,5)는 5이다. 경로는 2->5 단2개의 경로만 지나간다 그러나 1,3과을 지나치지지 않아 답이아니다

G(2,6)은 2->1->3->6이다. 즉 1,3을 지나갔다.

 

그렇다면 1,3을 지나갔다라는 것을 어떻게 알수있을까??

G(2,6)의 경로를 보면 2->1은 G(2,1)로 고쳐쓸수있다. 그리고 1->3은 G(1,3)으로 고칠수있고  3->6은 G(3,6)으로 고칠수 있다 즉 G(2,6)은 G(2,1) + G(1,3)+G(3,6) 이된다.

이것을 다시 쓰자면 s에서 출발해서 g h,의 교차로를 통해 건너가 최단거리를 구한다면

G(s,t) = G(s,g)+G(g,h)+G(h,t) 이거나 G(s,h)+G(h,g)+G(h,t) 일것임이 자명하다.

 

그렇기에 G(2,5) != G(2,1)+G(1,3)+G(3,6) ,

G(2,5)!= G(2,3)+G(3,1)+G(1,6) 이므로 답이될수없다 

따라서 이공식을 통해 g h를 건너 갈수있다는 것을 알수있다.

 

소스코드 : 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//By 콩순이냉장고
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
using namespace std;
struct dij {
    int cur, sumcost;
    bool flag;
    dij() {}
    dij(int cur, int sumcost) :cur(cur), sumcost(sumcost){}
};
struct cmp {
    bool operator()(dij &a, dij &b) {
        return a.sumcost> b.sumcost;
    }
};
 
int n, m, t;
int s, g, h;
vector<pair<intint>>v[2001];
vector<int> arrive;
void reset() {
    for (int i = 1; i <= n; i++) {
        v[i].clear();
    }
    arrive.clear();
}
void input() {
    cin >> n >> m >> t;
    cin >> s >> g >> h;
    for (int i = 0; i < m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        v[a].push_back({ b,c });
        v[b].push_back({ a,c });
    }
    for (int i = 0; i < t; i++) {
        int c;
        cin >> c;
        arrive.push_back(c);
    }
}
void dijkstra(int start,int *dist) {
 
    map<pair<intint>int> visit;
    priority_queue<dij, vector<dij>, cmp> pq;
    fill(dist+1, dist + n+1, 1e+9);
    dist[start] = 0;
    pq.push({ start,0 });
    
    while (!pq.empty()) {
        int cur = pq.top().cur;
        int sumcost = pq.top().sumcost;
 
        pq.pop();
        for (int i = 0; i < v[cur].size(); i++) {
            int next = v[cur][i].first;
            int cost = v[cur][i].second+sumcost;
            if (dist[next] > cost) {
                pq.push({ next,cost});
                dist[next] = cost;
            }
        }
    }
}
void solve()
{
    int dist_s[2001];
    int dist_g[2001];
    int dist_h[2001];
    
    dijkstra(s, dist_s);
    dijkstra(g, dist_g);
    dijkstra(h, dist_h);
    sort(arrive.begin(), arrive.end());
    for (int candidate : arrive) {
        int path1 = dist_s[g] + dist_g[h] + dist_h[candidate];
        int path2 = dist_s[h] + dist_h[g] + dist_g[candidate];
        if (path1 == dist_s[candidate] || path2 == dist_s[candidate])
            cout << candidate << " ";
    }
    cout << "\n";
}
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int test;
    cin >> test;
    while (test--) {
        input();
        solve();
        reset();
    }
}
cs

 

궁금한점 혹은 모르는점 

혹은 다른 어떤 아이디어든 좋습니다. 

댓글은 언제나 환영입니다.

 

'백준' 카테고리의 다른 글

백준 2568 전깃줄 - 2  (0) 2021.02.15
백준 3745 오름세  (0) 2021.02.15
백준 16235 나무 재테크  (0) 2021.02.15
백준 16920 확장 게임  (0) 2021.02.15
백준 1806 부분합  (0) 2021.02.15