Skip to content
本博客自 2023 年 4 月 4 日起转为归档状态,可能不再发表新的博文。点此了解博主的竞赛生涯
This blog has been archived by the owner since April 4, 2023. It may no longer have new updates.

S2OJ - 1498. 换乘

检测到 KaTeX 加载失败,可能会导致文中的数学公式无法正常渲染。

#题面

#题目背景

翠江城是一个交通发展的城市,城里的地铁四通八达。地铁一共有 nn 个站点,mm 条线路,每条线路连接两个站点, 可以在这两个站点之间双向通行。

#题目描述

特殊的是,翠江城的地铁由多家公司运营,乘坐每家公司的地铁都需要 11 元钱,但换乘同一家公司的地铁不需要再次付费。小 D 想从 11 号站点前往 nn 号站点,他想知道最小费用是多少。

#输入格式

输入第一行有两个正整数 n,mn, m 表示站点数和线路数。

接下来 mm 行,每行三个整数 pi,qi,cip_i, q_i, c_i ,表示这条线路连接的两个站点以及运营它的公司编号。

#输出格式

输出仅包括一行一个整数,表示答案。如果无法到达,输出 1-1

#输入输出样例

样例输入 #1

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

样例输出 #1

2

样例解释 #1

先乘坐公司 11 的地铁 132561 \to 3 \to 2 \to 5 \to 6,然后乘坐公司 22 的地铁 2782 \to 7 \to 8

样例输入 #2

4 3
1 2 1
2 3 2
3 4 1

样例输出 #2

3

#数据范围与约定

对于 30%30\% 的数据,满足 n1000n \leq 1000m2000m \leq 2000
对于另外 20%20\% 的数据,满足 ci4c_i \leq 4
对于 100%100\% 的数据,满足 2n1052 \leq n \leq 10^51m2×1051 \leq m \leq 2 \times 10^51ci1061 \leq c_i \leq 10^6piqip_i \ne q_i

#思路

考虑将每种颜色都建一个子图,子图内的点之间连费用为 00 的边。然后再考虑换乘,把所有子图中的点都练到对应的原图上的点,费用为 11。那么求这个新图的最短路即可。

#代码

C++
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
#include <iostream>
#include <cstring>
#include <deque>
#include <set>
#include <vector>

using std::cin;
using std::cout;
const char endl = '\n';

const int N = 1000005;

int n, m, id[N], last[N], dist[N];
bool vis[N];
std::set<int> cs;
std::vector<std::pair<int, int>> c[N], g[N];

void bfs() {
memset(dist, 0x3f, sizeof(dist));

std::deque<int> q;

dist[1] = 0;
q.emplace_back(1);

while (!q.empty()) {
int u = q.front();
q.pop_front();

if (vis[u]) continue;
vis[u] = true;

for (auto e : g[u]) {
int v = e.first,
w = e.second;

if (dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;

if (w) q.emplace_back(v);
else q.emplace_front(v);
}
}
}
}

int main() {
std::ios::sync_with_stdio(false);
cin.tie(nullptr);

cin >> n >> m;

for (int i = 1, u, v, c; i <= m; i++) {
cin >> u >> v >> c;

::c[c].emplace_back(u, v);
cs.insert(c);
}

int cnt = n;
for (int x : cs) {
for (auto e : c[x]) {
int u = e.first,
v = e.second;

if (last[u] != x) {
last[u] = x;
id[u] = ++cnt;
g[u].emplace_back(id[u], 1);
g[id[u]].emplace_back(u, 0);
}

if (last[v] != x) {
last[v] = x;
id[v] = ++cnt;
g[v].emplace_back(id[v], 1);
g[id[v]].emplace_back(v, 0);
}

g[id[u]].emplace_back(id[v], 0);
g[id[v]].emplace_back(id[u], 0);
}
}

bfs();

cout << (dist[n] == 0x3f3f3f3f ? -1 : dist[n]) << endl;

return 0;
}