[CSP-J 2023] 旅游巴士 题解
这题如果啥都不会,千万别忘了输出
-1 祈求 CCF 的施舍,能骗多少分就看缘分了
注意到
对所有满足特殊性质
具体地,设
vector<pair<int, int>> G[N];
int d[N][105];
int main() {
int n, m, kk;
scanf("%d%d%d", &n, &m, &kk);
while (m--) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
G[u].push_back({v, w});
}
memset(d, -1, sizeof d);
queue<pair<int, int>> q;
d[1][0] = 0;
q.push({1, 0});
while (q.size()) {
auto [u, i] = q.front();
q.pop();
for (auto [v, w] : G[u]) {
int j = (i + 1) % kk;
if (d[v][j] == -1) {
d[v][j] = d[u][i] + 1;
q.push({v, j});
}
}
}
printf("%d\n", d[n][0]);
return 0;
}
每条边有了时间限制,其实也不用怕,可以原地等待
比如当前的边需要的时间是
然后这样普通 BFS 就不行了,得用优先队列来贪心选取当前最小状态来拓展,本质上就是 Dijkstra 算法。
时间复杂度
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 10005;
vector<pair<int, int>> G[N];
int d[N][105];
int vis[N][105];
struct Node {
int u, i, d;
bool operator<(const Node &rhs) const {
return d > rhs.d;
}
};
int main() {
int n, m, kk;
scanf("%d%d%d", &n, &m, &kk);
while (m--) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
G[u].push_back({v, w});
}
memset(d, 0x3f, sizeof d);
priority_queue<Node> q;
q.push({1, 0, d[1][0] = 0});
while (q.size()) {
int u = q.top().u, i = q.top().i;
q.pop();
if (vis[u][i]) continue;
vis[u][i] = 1;
for (auto [v, w] : G[u]) {
int t = d[u][i], j = (i + 1) % kk;
if (t < w) t += (w - t + kk - 1) / kk * kk;
if (d[v][j] > t + 1) q.push({v, j, d[v][j] = t + 1});
}
}
if (d[n][0] == INF) d[n][0] = -1;
printf("%d\n", d[n][0]);
return 0;
}