CF20C Dijkstra? 题解
Content
给定一张 \(n\) 个点 \(m\) 条边的无向图,请判断是否有一条可行的从 \(1\) 到 \(n\) 的路径,有的话输出长度最短的,没有的话输出 -1
。
数据范围:\(2\leqslant n\leqslant 10^5\),\(0\leqslant m\leqslant 10^5\),每条边的长度不超过 \(10^6\)。
Solution
这道题的标题当中看上去是在误导你不用 \(\textsf{Dijkstra}\),其实已经给出了这道题目的做法就是:\(\textsf{Dijkstra}\)。为了优化复杂度,我用了堆优化 + \(\textsf{Dijkstra}\)。
那么 \(\textsf{Dijkstra}\) 如何做到能够输出路径呢?这里我们就需要用到一个 \(\textit{pre}\) 数组,其中 \(\textit{pre}_i\) 表示最短路径中在 \(i\) 点前面的点。我们可以在 \(\textsf{Dijkstra}\) 处理 \(\textit{dis}\) 数组的时候就把这个 \(pre\) 更新一遍,就像这样:
for(int i = h[x]; i; i = e[i].nxt) {
int y = e[i].to, z = e[i].v;
if(dis[y] > dis[x] + z) { //更新最短路
dis[y] = dis[x] + z, pre[y] = x; //更新最短路的长度和当前点在最短路上的前一个节点。
q.push(make_pair(-dis[y], y));
}
}
那么我们又如何判断是否存在从 \(1\) 到 \(n\) 最短路径呢?这里给出两种方法:
第一种,还记得我们在跑 \(\textsf{Dijkstra}\) 的时候要先做什么吗?没错,初始化 \(\textit{dis}\) 数组。由于是最短路,我们需要将这个 \(\textit{dis}\) 数组的初值设得尽可能大,又因为在数据范围中我们发现:
\(0\leqslant m\leqslant 10^5\),每条边的长度不超过 \(10^6\)。
所以我们就知道了,可能最长的最短路长度为 \(10^5\times 10^6=10^{11}\),因此我们需要开 long long,并将这个 \(\textit{dis}\) 数组赋初值赋在 \(10^{11}\) 以上,下面这一段以笔者在代码中赋的初值 \(10^{18}\) 为准。
然后我们就可以通过这个来判断是否存在到 \(n\) 的最短路径了:只需要判断是否有 \(\textit{dis}_n\neq10^{18}\) 即可,因为如果 \(\textit{dis}_n=10^{18}\),那么就说明 \(\textit{dis}_n\) 还从来没有更新过,自然也就不存在从 \(1\) 到 \(n\) 的最短路径了。
第二种,就要用到这一题中所引入的 \(\textit{pre}\) 数组了,我们可以从 \(n\) 开始,直接利用 \(x\leftarrow\textit{pre}_x\) 向前推最短路径上的节点,看是否能够推到 \(1\),如果最终不能够推到 \(1\) 就说明不存在从 \(1\) 到 \(n\) 的最短路径。
两种方法虽然看上去第一种的表述要多一些,但实际上这两种方法的实现程度都是不难的,因此推荐大家把两种写法都写一遍。
另外,我们也可以从这道题目中吸取一些教训:标题并不一定就决定了你的做题思路,你的做题思路应当从题面中通过思考而得出。
Code 1
const int N = 1e5 + 7, M = N << 1;
int n, m, u, v, w, cnt, fl, vis[N], h[M], ans[N], pre[N];
ll dis[N];
struct edge {int v, to, nxt;}e[M];
pq<pair<ll, int> > q;
iv a_e(int u, int v, int w) {e[++cnt] = (edge){w, v, h[u]}; h[u] = cnt;}
iv dj() {
F(i, 1, 100000) dis[i] = 1e18;
dis[1] = 0, q.push(mp(0, 1));
while(!q.empty()) {
int x = q.top().se; q.pop();
if(vis[x]) continue; vis[x] = 1;
E {
int y = e[i].to, z = e[i].v;
if(dis[y] > dis[x] + z) {
dis[y] = dis[x] + z, pre[y] = x;
q.push(mp(-dis[y], y));
}
}
}
}
int main() {
n = Rint, m = Rint;
F(i, 1, m) {
u = Rint, v = Rint, w = Rint;
a_e(u, v, w), a_e(v, u, w);
}
dj();
for(int cur = n; cur; cur = pre[cur]) ans[++ans[0]] = cur;
if(dis[n] != (ll)1e18) R(i, ans[0], 1) write(ans[i]), putchar(" \n"[i == n]);
else puts("-1");
return 0;
}
Code 2
const int N = 1e5 + 7, M = N << 1;
int n, m, u, v, w, cnt, fl, vis[N], h[M], ans[N], pre[N];
ll dis[N];
struct edge {int v, to, nxt;}e[M];
pq<pair<ll, int> > q;
iv a_e(int u, int v, int w) {e[++cnt] = (edge){w, v, h[u]}; h[u] = cnt;}
iv dj() {
F(i, 1, 100000) dis[i] = 1e18;
dis[1] = 0, q.push(mp(0, 1));
while(!q.empty()) {
int x = q.top().se; q.pop();
if(vis[x]) continue; vis[x] = 1;
E {
int y = e[i].to, z = e[i].v;
if(dis[y] > dis[x] + z) {
dis[y] = dis[x] + z, pre[y] = x;
q.push(mp(-dis[y], y));
}
}
}
}
int main() {
n = Rint, m = Rint;
F(i, 1, m) {
u = Rint, v = Rint, w = Rint;
a_e(u, v, w), a_e(v, u, w);
}
dj();
for(int cur = n; cur; cur = pre[cur]) {
ans[++ans[0]] = cur;
if(cur == 1) fl = 1;
}
if(fl) R(i, ans[0], 1) write(ans[i]), putchar(" \n"[i == n]);
else puts("-1");
return 0;
}
CF20C Dijkstra? 题解的更多相关文章
- 【算法】祭奠spfa 最短路算法dijspfa
题目链接 本题解来源 其他链接 卡spfa的数据组 题解堆优化的dijkstra 题解spfa讲解 来自以上题解的图片来自常暗踏阴 使用前向星链表存图 直接用队列优化spfa struct cmp { ...
- 【GDOI2018】所有题目和解题报告
使用说明:题意和数据范围都只是回忆内容,仅供参考.题解陆续补上. Day 1 第一题 题意:给定n个数字,要求划分成k的连续段使得每个连续段内的数字之和相同,求最大的k.n,Σai<=10^6. ...
- SCU-4527 NightMare2(Dijkstra+BFS) !!!错误题解!!!
错解警告!!! 描述 可怜的RunningPhoton又做噩梦了..但是这次跟上次不大一样,虽然他又被困在迷宫里,又被装上了一个定时炸弹,但是值得高兴的是,他发现他身边有数不清的财宝,所以他如果能带着 ...
- Newcoder Metropolis(多源最短路 + Dijkstra堆优化)题解
题目链接:https://www.nowcoder.com/acm/contest/203/I?tdsourcetag=s_pcqq_aiomsg来源:牛客网 思路:我们用用fa[i]表示距离i最近的 ...
- PAT甲题题解-1072. Gas Station (30)-dijkstra最短路
题意:从m个加油站里面选取1个站点,使得其离住宅的最近距离mindis尽可能地远,并且离所有住宅的距离都在服务范围ds之内.如果有很多相同mindis的加油站,输出距所有住宅平均距离最小的那个.如果平 ...
- PAT甲题题解-1111. Online Map (30)-PAT甲级真题(模板题,两次Dijkstra,同时记下最短路径)
题意:给了图,以及s和t,让你求s到t花费的最短路程.最短时间,以及输出对应的路径. 对于最短路程,如果路程一样,输出时间最少的. 对于最短时间,如果时间一样,输出节点数最少的. 如果最短路程 ...
- POJ 1797 Heavy Transportation(最短路&Dijkstra变体)题解
题意:给你所有道路的载重,找出从1走到n的所有路径中载重最大的,即路径最小值的最大值. 思路:和之前的POJ3268很像.我们用Dijkstra,在每次查找时,我们把最大的先拿出来,因为最大的不影响最 ...
- POJ 3268 Silver Cow Party(最短路&Dijkstra)题解
题意:有n个地点,有m条路,问从所有点走到指定点x再走回去的最短路中的最长路径 思路:用Floyd超时的,这里用的Dijkstra. Dijkstra感觉和Prim和Kruskal的思路很像啊.我们把 ...
- 【CF20C】Dijkstra?(DIJKSTRA+HEAP)
没什么可以说的 做dijk+heap模板吧 以后考试时候看情况选择SFPA和DIJKSTRA ; ..]of longint; dis:..]of int64; a:..]of int64; b:.. ...
随机推荐
- DotNetty实现WebSocket的简单使用
工作中项目是物联网项目的,管理平台又是bs架构. 如果用 Socket 的话,Web 端还需要转发,就全部统一采用了 WebSocket . DotNet 平台上的 WebSocket 实现有很多种, ...
- 统计学习2:线性可分支持向量机(Scipy实现)
1. 模型 1.1 超平面 我们称下面形式的集合为超平面 \[\begin{aligned} \{ \bm{x} | \bm{a}^{T} \bm{x} - b = 0 \} \end{aligned ...
- CF1264D1 Beautiful Bracket Sequence (easy version)
考虑在一个确定的括号序列中,我们可以枚举中间位置,按左右最长延伸出去的答案计算. 我们很自然的思考,我们直接维护左右两边,在删除一些字符后能够延伸的最长长度. 我们设\(f_{i,j}\)为\(i\) ...
- CSS浮动效果
#div1{ background-color: yellow; width: 150px; height:150px; position: absolute; top:150px; left: 15 ...
- logname
logname命令用来显示用户名称. 语法 logname(选项) 选项 --help:在线帮助: --vesion:显示版本信息.
- 64-Unique Binary Search Trees
96. Unique Binary Search Trees My Submissions Question Editorial Solution Total Accepted: 82788 Tota ...
- msql_5.6.46编译问题
初始化数据库的时候, 使用mysql_install_db 必须是再mysql安装的目录下用相对路径去进行初始化 CentOs6.9必须先把/etc/my.cnf 先改为其他名字,之后再把安装目录下s ...
- CMakeLists.txt添加多个源代码
coos2d-x 3.17.2 C++工程,安卓编译使用CMake,按照模板给的写法,只能一个一个源文件添加:如果需要添加大量的C++源代码,这种方式肯定不可取:原来的写法: 1 list(APPEN ...
- A Child's History of England.36
CHAPTER 11 ENGLAND UNDER MATILDA AND STEPHEN The King was no sooner dead than all the plans and sche ...
- 13. 搭建arm-linux-gcc交叉编译环境
1.下载工具并解压 下载路径 http://www.arm9.net/download.asp 将 arm-linux-gcc-4.5.1-v6-vfp-20120301.tgz 拷贝到 Linux ...