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? 题解的更多相关文章

  1. 【算法】祭奠spfa 最短路算法dijspfa

    题目链接 本题解来源 其他链接 卡spfa的数据组 题解堆优化的dijkstra 题解spfa讲解 来自以上题解的图片来自常暗踏阴 使用前向星链表存图 直接用队列优化spfa struct cmp { ...

  2. 【GDOI2018】所有题目和解题报告

    使用说明:题意和数据范围都只是回忆内容,仅供参考.题解陆续补上. Day 1 第一题 题意:给定n个数字,要求划分成k的连续段使得每个连续段内的数字之和相同,求最大的k.n,Σai<=10^6. ...

  3. SCU-4527 NightMare2(Dijkstra+BFS) !!!错误题解!!!

    错解警告!!! 描述 可怜的RunningPhoton又做噩梦了..但是这次跟上次不大一样,虽然他又被困在迷宫里,又被装上了一个定时炸弹,但是值得高兴的是,他发现他身边有数不清的财宝,所以他如果能带着 ...

  4. Newcoder Metropolis(多源最短路 + Dijkstra堆优化)题解

    题目链接:https://www.nowcoder.com/acm/contest/203/I?tdsourcetag=s_pcqq_aiomsg来源:牛客网 思路:我们用用fa[i]表示距离i最近的 ...

  5. PAT甲题题解-1072. Gas Station (30)-dijkstra最短路

    题意:从m个加油站里面选取1个站点,使得其离住宅的最近距离mindis尽可能地远,并且离所有住宅的距离都在服务范围ds之内.如果有很多相同mindis的加油站,输出距所有住宅平均距离最小的那个.如果平 ...

  6. PAT甲题题解-1111. Online Map (30)-PAT甲级真题(模板题,两次Dijkstra,同时记下最短路径)

    题意:给了图,以及s和t,让你求s到t花费的最短路程.最短时间,以及输出对应的路径.   对于最短路程,如果路程一样,输出时间最少的. 对于最短时间,如果时间一样,输出节点数最少的.   如果最短路程 ...

  7. POJ 1797 Heavy Transportation(最短路&Dijkstra变体)题解

    题意:给你所有道路的载重,找出从1走到n的所有路径中载重最大的,即路径最小值的最大值. 思路:和之前的POJ3268很像.我们用Dijkstra,在每次查找时,我们把最大的先拿出来,因为最大的不影响最 ...

  8. POJ 3268 Silver Cow Party(最短路&Dijkstra)题解

    题意:有n个地点,有m条路,问从所有点走到指定点x再走回去的最短路中的最长路径 思路:用Floyd超时的,这里用的Dijkstra. Dijkstra感觉和Prim和Kruskal的思路很像啊.我们把 ...

  9. 【CF20C】Dijkstra?(DIJKSTRA+HEAP)

    没什么可以说的 做dijk+heap模板吧 以后考试时候看情况选择SFPA和DIJKSTRA ; ..]of longint; dis:..]of int64; a:..]of int64; b:.. ...

随机推荐

  1. 【状压dp】Hamiton路径

    描述 给定一张 n(n≤20) 个点的带权无向图,点从 0~n-1 标号,求起点 0 到终点 n-1 的最短Hamilton路径. Hamilton路径的定义是从 0 到 n-1 不重不漏地经过每个点 ...

  2. 洛谷 P4663 - [BalticOI 2008]魔法石(dp)

    题面传送门 A:我该是有多无聊来写这种题的题解啊 B:大概是因为这题题解区里没有题解所以我来写一篇了,说明我有高尚的济世情怀(大雾 跑题了跑题了 首先看到字典序第 \(i\) 小小可以自然地想到按位决 ...

  3. 一类巧妙利用利用失配树的序列DP

    I.导入 求长度为\(\text{len}\)的包含给定连续子串\(\text{T}\)的 0/1 串的个数.(\(|T|<=15\)) 通常来说这种题目应该立刻联想到状压 DP 与取反集--这 ...

  4. 55. Binary Tree Preorder Traversal

    Binary Tree Preorder Traversal My Submissions QuestionEditorial Solution Total Accepted: 119655 Tota ...

  5. 在Linux下搭建nRF51822的开发烧写环境(makefile版)

    http://www.qingpingshan.com/m/view.php?aid=394836

  6. 【原创】基于RPA的软件功能自动化测试

    简介:1个功能自动化的框架 特点:OCR识别文字内容,pylackey对比图像相似度 代码极简 适用于绝大部分场景 只需要对按钮进行截图 配合第三方库可以生成漂亮的测试报告 文件结构:action-- ...

  7. Hadoop入门 运行环境搭建

    模板虚拟机 目录 模板虚拟机 1 硬件 2 操作系统 3 IP地址和主机名称 vm windows10 Hadoop100服务器 远程访问工具 其他准备 克隆虚拟机 克隆 修改主机名/ip 安装jdk ...

  8. 纯CSS圆环与圆

    1. 两个标签的嵌套: <div class="element1"> <div class="child1"></div> ...

  9. Java——数组的定义与使用

    数组的定义与使用 1.数组的基本概念 (1)数组的动态初始化: 数组首先先开辟内存空间,而后再使用索引进行内容的设置,这种定义数组的方式称为动态初始化 数组是引用数据类型,存在有内存分配问题.在使用前 ...

  10. JavaIO——File类

    1.File文件类 File类(描述具体文件或文件夹的类):是唯一一个与文件本身操作有关的程序类,可完成文件的创建.删除.取得文件信息等操作.但不能对文件的内容进行修改. (1)File类的基本使用 ...