白兰花
一道最短路。
给定一个
个点 条边的无向图 G,求 G 上 1 到其他点的最短路的长度。
当然,只要求最短路未免过于简单,假设一条路径上的边权依次为
,于是定义 为路径长度,他希望你能帮他求出在这个定义下的最短路。
如果不联通,请输出
1000000000000000000
。
考场思路
还是不好做。
考虑转换为一条边的边权可以变成
不知道怎么处理可能先变 dijkstra
一次钦定先变
code
#include <bits/stdc++.h>
#define rep(i, j, k) for(int i = (j); i <= (k); i ++)
#define per(i, j, k) for(int i = (j); i >= (k); i --)
#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<LL, int> PLI;
const int N = 6e5 + 5, M = 2e6 + 5, INF = 0x3f3f3f3f;
const LL mod = 1e9 + 7;
int n, m;
int h[N], to[M << 1], val[M << 1], nxt[M << 1], cnt;
void add(int u, int v, int w) {
to[++ cnt] = v, val[cnt] = w, nxt[cnt] = h[u], h[u] = cnt;
}
struct Node {
int u, v, w;
} edge[M];
LL dist[N], ans[N];
bool st[N];
/*
一条边边权变成0,一条边边权变成2倍
先变0还是先变2倍。。。不会
跑两边取min试试(
三层?
u->v w
u'->v' w
u'' -> v'' w
u->v' 0
u' -> v'' 2*w
*/
void dijkstra() {
rep(i, 1, n * 3) dist[i] = 1e18, st[i] = false;
priority_queue<PLI, vector<PLI>, greater<PLI> > q;
q.push({0, 1});
dist[1] = 0;
while(q.size()) {
int u = q.top().se;
q.pop();
if(st[u]) continue;
st[u] = true;
for(int i = h[u]; i; i = nxt[i]) {
int v = to[i], w = val[i];
if(dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;
q.push({dist[v], v});
}
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
cin >> n >> m;
rep(i, 1, m) { // 第一遍钦定先变0在变2倍
int u, v, w;
cin >> u >> v >> w;
edge[i] = {u, v, w};
add(u, v, w), add(v, u, w);
add(u + n, v + n, w), add(v + n, u + n, w);
add(u + n * 2, v + n * 2, w), add(v + n * 2, u + n * 2, w);
add(u, v + n, 0), add(v, u + n, 0);
add(u + n, v + n * 2, w * 2), add(v + n, u + 2 * n, w * 2);
}
dijkstra();
rep(i, 1, n) ans[i] = min(dist[i], dist[i + n * 2]);
cnt = 0;
memset(h, 0, sizeof h);
rep(i, 1, m) {
int u = edge[i].u, v = edge[i].v, w = edge[i].w;
add(u, v, w), add(v, u, w);
add(u + n, v + n, w), add(v + n, u + n, w);
add(u + n * 2, v + n * 2, w), add(v + n * 2, u + n * 2, w);
add(u, v + n, w * 2), add(v, u + n, w * 2);
add(u + n, v + n * 2, 0), add(v + n, u + n * 2, 0);
}
dijkstra();
rep(i, 1, n) ans[i] = min(ans[i], dist[i + n * 2]);
rep(i, 2, n) cout << ans[i] << ' ';
return 0;
}
贴个官方解法,比我的好处理。
不好处理,考虑把他看成路径上有一条边要支付
两次代价,一条边可以免费,然后要最小化权值。
这样一条路径想要权值最小,一定会,并且也
不能更小。
因此考虑建立分层图,表示从 走到 ,是
否会有一条边支付了两次,是否有一条边免费了。
时间复杂度。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现