💡 Knowledge is p|

Panda_LYL

园龄:4个月粉丝:0关注:0

2024-10-22 21:33阅读: 24评论: 0推荐: 0

P9751 [CSP-J 2023] 旅游巴士 题解

思路

首先,举一个例子,假如说 小Z 到了入口,但是没到时间,所以没法进去,该怎么办?

当然是等 k 个时间单位呀.

除此之外,像到了其他景区,但是还没开门怎么办 ? 继续等 k 的非负整数倍时间呀.

知道这个后,我们先定义状态 fi,j,表示到达点 i 时,路径长度(即时间) mod k 的最早时间.

目标:fn,0.

为什么要取模呢? 因为这样不仅可以方便计算,而且题面中说到,到达和离开景区的时间均要是 k 的非负整数倍数.所以当 j=0 时,就说明是 k 的倍数了.

转移

显然,这题可以使用最短路,我们在求最短路的同时进行转移.关于最短路算法,建议选择优先队列优化过后Dijkstra.

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
int n, m, k;
int f[10004][102]; // f[i][j]表示到点i,长度%k余数为j的最早时间
struct q{
int id, mod, cost; // 节点编号,j,时间
bool friend operator < (q a, q b) { // 重载小于运算符
return a.cost > b.cost;
}
};
struct node {
int v, w;
};
int vis[10004][102];
vector<node> g[10004]; // vector 存图
priority_queue<q> pq; // 优先队列
void dijkstra() {
pq.push((q){1, 0, 0}); // 最开始的元素
while (!pq.empty()) {
q h = pq.top();
pq.pop();
int u = h.id, j = h.mod, cost = h.cost;
// 没有被访问过,更新 f[u][j]
if (!vis[u][j]) f[u][j] = cost, vis[u][j] = 1;
else continue;
for (int i = 0; i < g[u].size(); i++) {
int v = g[u][i].v, w = g[u][i].w;
int t = f[u][j];
while (t < w) t += k; // 还没有开门,就继续等
if (t + 1 < f[v][(j+1)%k]) // 更早的时间
pq.push((q){v, (j+1)%k, t + 1}); // 放入优先队列
}
}
}
int main() {
scanf("%d%d%d", &n, &m, &k);
for (int i = 1; i <= m; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
g[u].push_back((node){v, w});
}
memset(f, 0x3f, sizeof(f)); // 初始化,较大的初值
dijkstra();
if (f[n][0] != 0x3f3f3f3f) printf("%d", f[n][0]); // 不是初值,说明可以到达
else printf("-1");
return 0;
}

本文作者:Panda_LYL

本文链接:https://www.cnblogs.com/panda-lyl/p/18493786

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Panda_LYL  阅读(24)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起