--- 这里是 cjiaw 的小窝(●'◡'●) ---

正在玩命加载中......

洛谷__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;
}

 

posted @ 2025-11-16 13:55  wwjjw  阅读(24)  评论(0)    收藏  举报