Solution -「CF 575G」Run for beer
Link.
给定 个点 条边的无向图,边有边权,一个人初始速度为 ,每走一条边速度 ,求从 走到 的最小耗时。
,。
直观地,路径长度即为把经过的边权从低位到高位写成的十进制数。
首先排除前导 ——把从终点出发,仅走边权为 的边可达的结点全部与终点缩点。此时的最短路需要保证路径条数最少的前提下保证字典序最小。BFS 分层,维护当前层外围最优的一堆结点,用它们向下层扩展直到到达起点。
#include <queue>
#include <cstdio>
#include <vector>
const int MAXN = 2e5, MAXM = 2e5;
int n, m, ecnt, head[MAXN + 5], d[MAXN + 5], suf[MAXN + 5];
bool vis[MAXN + 5];
std::vector<int> curp, nxtp;
std::queue<int> que;
struct Edge { int to, cst, nxt; } graph[MAXM * 2 + 5];
inline void link ( const int s, const int t, const int c ) {
graph[++ ecnt] = { t, c, head[s] };
head[s] = ecnt;
}
inline void initReach () {
for ( int i = 1; i <= n; ++ i ) d[i] = -1;
d[1] = 0, que.push ( 1 );
for ( int u; ! que.empty (); ) {
u = que.front (), que.pop ();
for ( int i = head[u], v; i; i = graph[i].nxt ) {
if ( ! ~ d[v = graph[i].to] ) {
d[v] = d[u] + 1, que.push ( v );
}
}
}
}
inline int zeroReach () {
int mind = d[n];
curp.push_back ( n ), vis[n] = true;
for ( int cur = 0; cur ^ curp.size (); ++ cur ) {
int u = curp[cur];
for ( int i = head[u], v; i; i = graph[i].nxt ) {
if ( ! vis[v = graph[i].to] && ! graph[i].cst ) {
curp.push_back ( v ), vis[v] = true, suf[v] = u;
if ( mind > d[v] ) mind = d[v];
}
}
}
return mind;
}
int main () {
scanf ( "%d %d", &n, &m );
for ( int i = 1, u, v, w; i <= m; ++ i ) {
scanf ( "%d %d %d", &u, &v, &w ), ++ u, ++ v;
link ( u, v, w ), link ( v, u, w );
}
initReach ();
int dist = zeroReach ();
bool zero = true;
for ( int l = dist; l; -- l ) {
int dig = 10;
for ( int u: curp ) {
for ( int i = head[u], v; i; i = graph[i].nxt ) {
if ( d[v = graph[i].to] + 1 == l && graph[i].cst < dig ) {
dig = graph[i].cst;
}
}
}
if ( dig ) zero = false;
if ( l == 1 || ! zero ) putchar ( dig ^ '0' );
for ( int u: curp ) {
for ( int i = head[u], v; i; i = graph[i].nxt ) {
if ( d[v = graph[i].to] + 1 == l && graph[i].cst == dig && ! vis[v] ) {
vis[v] = true, nxtp.push_back ( v ), suf[v] = u;
}
}
}
curp = nxtp, nxtp.clear ();
}
if ( zero ) putchar ( '0' );
int ans = 1, u;
for ( u = 1; u ^ n; ++ ans, u = suf[u] );
printf ( "\n%d\n0", ans ), u = 1;
do printf ( " %d", ( u = suf[u] ) - 1 ); while ( u ^ n );
putchar ( '\n' );
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现