Snuke's Subway Trip: Dijkstra's Algorithm
Problem Statement (See: http://arc061.contest.atcoder.jp/tasks/arc061_c)
Snuke's town has a subway system, consisting of N stations and M railway lines. The stations are numbered 1 through N. Each line is operated by a company. Each company has an identification number.
The i-th ( 1≤i≤M ) line connects station pi and qi bidirectionally. There is no intermediate station. This line is operated by company ci.
You can change trains at a station where multiple lines are available.
The fare system used in this subway system is a bit strange. When a passenger only uses lines that are operated by the same company, the fare is 1 yen (the currency of Japan). Whenever a passenger changes to a line that is operated by a different company from the current line, the passenger is charged an additional fare of 1 yen. In a case where a passenger who changed from some company A's line to another company's line changes to company A's line again, the additional fare is incurred again.
Snuke is now at station 1 and wants to travel to station N by subway. Find the minimum required fare.
Constraints
- 2≤N≤10^5
- 0≤M≤2×10^5
- 1≤pi≤N (1≤i≤M)
- 1≤qi≤N (1≤i≤M)
- 1≤ci≤10^6 (1≤i≤M)
- pi≠qi (1≤i≤M)
Input
The input is given from Standard Input in the following format:
N M p1 q1 c1 : pM qM cM
Output
Print the minimum required fare. If it is impossible to get to station N by subway, print -1
instead.
Sample Input 1
3 3 1 2 1 2 3 1 3 1 2
Sample Output 1
1
Use company 1's lines: 1 → 2 → 3. The fare is 1 yen.
Sample Input 2
8 11 1 3 1 1 4 2 2 3 1 2 5 1 3 4 3 3 6 3 3 7 3 4 8 4 5 6 1 6 7 5 7 8 5
Sample Output 2
2
First, use company 1's lines: 1 → 3 → 2 → 5 → 6. Then, use company 5's lines: 6 → 7 → 8. The fare is 2 yen.
Sample Input 3
2 0
Sample Output 3
-1
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long ll_t; 5 6 #define INF 1E9 7 8 ll_t pack(ll_t x, ll_t y) { 9 return x * 1E9 + y; 10 } 11 12 using edge = pair<ll_t, int>; 13 14 struct Dist { 15 ll_t v; 16 int d; 17 Dist(ll_t v_, int d_ = INF) : v(v_), d(d_) { } 18 bool operator < (const Dist& rhs) const { 19 return d > rhs.d; 20 } 21 }; 22 23 int N; 24 int M; 25 unordered_map<ll_t, vector<edge>> graph; 26 unordered_map<ll_t, int> dist; 27 unordered_set<ll_t> done; 28 29 int main() { 30 scanf("%d%d", &N, &M); 31 32 for (int i = 1; i <= M; i++) { 33 int p, q, c; 34 scanf("%d%d%d", &p, &q, &c); 35 graph[pack(p, c)].push_back(edge(pack(q, c), 0)); 36 graph[pack(q, c)].push_back(edge(pack(p, c), 0)); 37 38 graph[pack(p, c)].push_back(edge(pack(p, 0), 0)); 39 graph[pack(p, 0)].push_back(edge(pack(p, c), 1)); 40 graph[pack(q, c)].push_back(edge(pack(q, 0), 0)); 41 graph[pack(q, 0)].push_back(edge(pack(q, c), 1)); 42 } 43 44 priority_queue<Dist> q; 45 dist[pack(1, 0)] = 0; 46 q.push(Dist(pack(1, 0), 0)); 47 while (!q.empty()) { 48 Dist t = q.top(); 49 q.pop(); 50 if (done.count(t.v)) continue; 51 done.insert(t.v); 52 53 for (auto& kv : graph[t.v]) { 54 ll_t u = kv.first; 55 int d = kv.second; 56 int tmp = dist[t.v] + d; 57 if (dist.count(u) == 0 || tmp < dist[u]) { 58 dist[u] = tmp; 59 q.push(Dist(u, tmp)); 60 } 61 } 62 } 63 if (dist.count(pack(N, 0)) == 0) 64 printf("-1\n"); 65 else 66 printf("%d\n", dist[pack(N, 0)]); 67 return 0; 68 }