Loading

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

思路

定义 \(d_{i,j}\) 表示从 \(1\) 走到 \(i\),并且满足 \(t \bmod k = j\) 的最小的符合题意的 \(t\)

然后就可以直接跑一遍 Dijkstra 即可。

当要计算一条 \(u \to v\) 的边 \(w\) 时,如果当前时间不够无法达到 \(w\),那么需要将时间提到第一个时间大于 \(w\),并且模 \(k\) 相同的 \(x\) 即可。

code

#include <bits/stdc++.h>
#define fst first
#define snd second
#define re register

using namespace std;

typedef pair<int,int> pii;
const int N = 1e4 + 10,M = 2e4 + 10,K = 110,inf = 0x3f3f3f3f;
int n,m,k;
int d[N][K];
int idx,h[N],ne[M],e[M],w[M];
bool vis[N][K];

inline int read(){
    int r = 0,w = 1;
    char c = getchar();
    while (c < '0' || c > '9'){
        if (c == '-') w = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9'){
        r = (r << 3) + (r << 1) + (c ^ 48);
        c = getchar();
    }
    return r * w;
}

inline void add(int a,int b,int c){
    ne[idx] = h[a];
    e[idx] = b;
	w[idx] = c;
    h[a] = idx++;
}

inline int up(int a,int b){
	if (a % b == 0) return a / b;
	return a / b + 1;
}

inline int get(int x,int y){
	if (x >= y) return x;
	return up(y - x,k) * k + x;
}

inline void dijkstra(int s){
    priority_queue<pii,vector<pii>,greater<pii>> q;
    d[s][0] = 0;
    q.push({0,s});
    while (!q.empty()){
        pii t = q.top();
        q.pop();
		int dist = t.fst % k;
        if (vis[t.snd][dist]) continue;
		vis[t.snd][dist] = true;
		for (re int i = h[t.snd];~i;i = ne[i]){
			int j = e[i],lim = w[i];
			int ndist = (dist + 1) % k,ntim = get(t.fst,lim) + 1;
			if (d[j][ndist] > ntim){
				d[j][ndist] = ntim;
				q.push({d[j][ndist],j});
			}
		}
    }
}

int main(){
    memset(h,-1,sizeof(h));
    memset(d,inf,sizeof(d));
    n = read();
    m = read();
    k = read();
    for (re int i = 1;i <= m;i++){
        int a,b,c;
        a = read();
        b = read();
		c = read();
        add(a,b,c);
    }
    dijkstra(1);
    if (d[n][0] >= inf) puts("-1");
    else printf("%d",d[n][0]);
    return 0;
}
posted @ 2023-10-29 00:49  BeautifulWish  阅读(422)  评论(0编辑  收藏  举报