洛谷__P9751 [CSP-J 2023] 旅游巴士(dijkstra)
题目链接:P9751 [CSP-J 2023] 旅游巴士 - 洛谷
题目大意:
- 一个景区有 n 个地点,m 条有开放时间限制的单向道路。
- 从 1 号入口进,n 号出口出。
- 巴士每 k 时刻在入口和出口发车/收车 (意味着到达和离开景区的时间都必须是 的非负整数倍),
- 每条道路通过耗时 1,但只能在开放时间 t[i] 之后走。
- 同时不能在任何地点(包括景区入口和出口)或者道路上停留
- 求从入口坐巴士到出口坐巴士离开的最早时刻(k 的倍数),若无法到达输出 -1。
- 对于所有测试数据有:,,,
思路:
观察到 k 的值很小,很容易想到分层图
建立二维 dis[N][K]:表示 从起点走到点 i 在 j 时刻(mod k)符合条件下的最短时间
如果当前时间无法到达下个节点,那说明到达起点的时间要 加上时间的差值除 k 且向上取整
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<set>
#include<map>
#include<unordered_set>
#include<unordered_map>
#include<bitset>
#include<tuple>
#define inf 72340172838076673
#define int long long
#define endl '\n'
#define F first
#define S second
#define mst(a,x) memset(a,x,sizeof (a))
using namespace std;
typedef pair<int, int> pii;
const int N = 20086, mod = 998244353;
int n, m, k;
int h[N], e[N], ne[N], t[N], idx;
int dis[N][108];
bool st[N][108];
struct node {
int d, u, f;
bool operator<(const node &b)const {
return d > b.d;
}
};
priority_queue<node> q;
void add(int a, int b, int c) {
t[idx] = c;
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
void dij() {
mst(dis, 1);
dis[1][0] = 0;
q.push({0, 1, 0});
while (q.size()) {
auto [dd, u, f] = q.top();
q.pop();
if (st[u][f]) continue;
st[u][f] = true;
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
int nf = (f + 1) % k;//当前时间点+1
int d = dd;//拷贝使用,直接使用会更改结构体里的值,影响后续结果
if (t[i] > d) d += (t[i] - d + k - 1) / k * k;//向上取整
if (dis[j][nf] > d + 1) {
dis[j][nf] = d + 1;
q.push({dis[j][nf], j, nf});
}
}
}
}
void solve() {
mst(h, -1);
cin >> n >> m >> k;
for (int i = 1; i <= m; i++) {
int a, b, c;
cin >> a >> b >> c;
add(a, b, c);
}
dij();
if (dis[n][0] > inf / 2) dis[n][0] = -1;
cout << dis[n][0] << endl;//终点不停留直接上车
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T = 1;
// cin >> T;
while (T--) solve();
return 0;
}

浙公网安备 33010602011771号