首页 > 其他分享 >[ABC342E] Last Train 题解

[ABC342E] Last Train 题解

时间:2024-02-27 19:56:08浏览次数:20  
标签:ch Last int 题解 站点 vis Train now dis

洛谷传送门

原题传送门

题意

给出一些由 \((l,d,k,c,A,B)\) 描述的列车,表示每当时间为 \(l,l+d,l+2d,\cdots,l+(k-1)d\) 时有一半列车从 \(A\) 出发,经过 \(c\) 的时间到达 \(B\)。问如果从站点 \(i,i\in(0,n)\) 出发要去站点 \(n\),最晚什么时候到达站点 \(i\) 可以去到站点 \(n\)。

分析

因为是从所有站点去到站点 \(n\),不难想到反过来 BFS 出从 \(n\) 出发回到各个站点的“最短时间”(因为是反过来所以就是原本的最晚时间)。然后就是朴素的 BFS 了(好像是 SPFA?),这里不再赘述。

代码

#include <bits/stdc++.h>
#define int long long
#define inf 0x7fffffffffffffff
#define N 200005
using namespace std;
int n, m, dis[N];
int head[N], to[N], nxt[N], line[N], tot;
bool vis[N];

struct node {
	int l, d, k, c, A, B;
} t[N];

inline int read(int &x) {
	char ch = x = 0;
	int m = 1;
	while (ch < '0' || ch > '9') {
		ch = getchar();
		if (ch == '-') m *= -1;
	}
	while (ch >= '0' && ch <= '9') {
		x = (x << 1) + (x << 3) + ch - 48;
		ch = getchar();
	}
	x *= m;
	return x;
}

inline void print(int x) {
	if (x < 0) putchar('-'), x = -x;
	static int stk[50];
	int top = 0;
	do {
		stk[top++] = x % 10;
		x /= 10;
	} while (x);
	while (top) {
		putchar(stk[--top] + 48);
	}
	putchar('\n');
	return ;
}

inline void add(int u, int v, int x) {
	to[tot] = v;
	line[tot] = x;
	nxt[tot] = head[u];
	head[u] = tot++;
	return ;
}

inline void bfs() {
	queue<int> q;
	q.push(n);
	dis[n] = inf; //从 n 出发 BFS
	while (!q.empty()) {
		int x = q.front();
		q.pop();
		vis[x] = 0;
		for (int i = head[x]; ~i; i = nxt[i]) {
			int v = to[i], l = line[i];
			if (dis[x] - t[l].c - t[l].l < 0) continue; //已经错过了第一班车,没法往回了
			int now = min(t[l].k - 1, (dis[x] - t[l].c - t[l].l) / t[l].d);
			now = now * t[l].d + t[l].l; //计算出“最近的”那一班车
			if (dis[v] < now) {
				dis[v] = now; //更新 dis
				if (!vis[v]) vis[v] = 1, q.push(v);
			}
		}
	}
	return ;
}

signed main() {
	memset(head, -1, sizeof head);
	read(n), read(m);
	for (int i = 1; i <= n; i++) dis[i] = -inf;
	for (int i = 1; i <= m; i++) {
		read(t[i].l), read(t[i].d), read(t[i].k), read(t[i].c), read(t[i].A), read(t[i].B);
		add(t[i].B, t[i].A, i);
	}
	bfs();
	for (int i = 1; i <= n - 1; i++) {
		if (dis[i] == -inf) printf("Unreachable\n"); //无法到达的
		else printf("%lld\n", dis[i]);
	}
	return 0;
}

标签:ch,Last,int,题解,站点,vis,Train,now,dis
From: https://www.cnblogs.com/iloveoi/p/18037756

相关文章

  • [ABC342C] Many Replacement 题解
    洛谷传送门原题传送门题意给出由小写字母初始字符串,每次操作将字符串中所有为\(c\)的字符改为\(d\)。输出最终的字符串。分析很明显只需要开一个\(fa\)数组,其中\(fa[i]=j\)表示字母\(i\)被改为了\(j\)。对于每次操作只需要遍历\(26\)个字母,将\(fa[i]=c\)的那些......
  • [ABC341E] Alternating String 题解
    题目传送门原题传送门题意给出长为\(n\)的01串,如果一个子串01交替出现,则称其为“好的”。有\(q\)次询问,把\([x,y]\)中的每一位反转或者询问\([x,y]\)是否是“好的”。分析一眼线段树。用线段树维护区间是否是“好的”,每个节点维护最左段和最右端的值,pushup和q......
  • [ABC342G] Retroactive Range Chmax 题解
    洛谷传送门原题传送门题意维护一个数列,有以下三个操作:区间最值操作,即将\([l,r]\)区间内的\(A_i\)变成\(\max(A_i,v)\)。删除操作操作,即将第\(i\)次操作删除,保证第\(i\)次操作是操作\(1\),且未被删除。注:仅删除第\(i\)次操作,后续操作仍然在。查询,询问当前的......
  • P1013 进制位 题解
    题注题目传送门这篇题解其实是上一篇题解(Llf0703同志)证明过程的完善(其实就是思路一样了啦),来让入门者或追求严谨者对证明过程更加了解。题目分析\(3\leqn\leq9\),也即数字的个数\(N\leq8\)。研究样例发现,\(N\)与进制\(R\),以及数字对应两位数个数\(M\)与数字本身......
  • Pursuit For Artifacts 题解(图论)
    PursuitForArtifacts题解题目给定一张\(n\)个点\(m\)条边的简单无向连通图,边有边权,边权要么为\(0\),要么为\(1\)。每条边只能通过一次(两个方向加起来只能通过一次)。求是否存在一条从\(a\)到\(b\)的路径,满足路径上至少存在一条权为\(1\)的边。\(1\leqn,m\l......
  • CF1864C 题解
    \(x=2^k\)是好做的,每次以\(2^{k-1}\)为因数即可。对于其他情况,考虑每次让\(x\)减去其二进制下最低位的\(1\)直至变成\(2^k\)。这种策略下显然每个数只会在以上两个大步骤下取到,故每个数使用不超过\(2\)次。同时操作次数在\(O(\logn)\)这个量级。#include<bits/......
  • P7086 题解
    考虑把每个字符串的前\(k\)位和后\(k\)位看成点,字符串看成边,那么一个字符串前缀后缀至少有一个是相似群体的前缀后缀,看成这条边的两个端点至少有一个被选中。那么这就变成了一个最小点覆盖问题。考虑匈牙利算法算出答案,然后考虑如何构造答案。考虑右边没有被匹配的点,选中这......
  • AT_abc317_f 题解
    调了一小时结果发现爆longlong了。考虑数位dp,具体来说,设计状态\(dp_{i,r_1,r_2,r_3,mx_1,mx_2,mx3_,c_1,c_2,c_3}\)表示当前考虑到第\(i\)位,\(x_1,x_2,x_3\)模\(a_1,a_2,a_3\)等于\(r_1,r_2,r_3\)三个数是否达到\(n\)的上界以及是否全部是\(0\)。然后从高到低枚......
  • AT_joisc2019_j 题解
    先考虑这个式子:\[\sum_{j=1}^{M}|C_{k_{j}}-C_{k_{j+1}}|\]一定是在\(C\)有序时取到,具体证明很简单各位读者自己证明。那么现在式子变成:\[\sum{V}+2\times({C_{\max}-C_{\min}})\]这个时候一个常见的技巧是将\(C\)排序。这个时候就可以定义状态:\[dp_{i,j}=\s......
  • CF1862G 题解
    首先这个查询操作很迷,考虑先化简查询操作。不难发现由于每次是加上一个逆的等差序列,因此一次操作完每个数与它的前驱之差一定会减少,因此加上等差序列的次数就等于全局每个数与它的前驱之差最大值。又因为会排序去重,所以最后剩下来的数一定是最开始的数一路加过来的,至此我们发现......