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:.. ...
随机推荐
- 洛谷 P5279 - [ZJOI2019]麻将(dp 套 dp)
洛谷题面传送门 一道 dp 套 dp 的 immortal tea 首先考虑如何判断一套牌是否已经胡牌了,考虑 \(dp\).我们考虑将所有牌按权值大小从大到小排成一列,那我们设 \(dp_ ...
- 各种多项式操作的 n^2 递推
zszz,使用 NTT 可以在 \(\mathcal O(n\log n)\) 的时间内求出两个多项式的卷积.以及一个多项式的 \(\text{inv},\ln,\exp,\text{sqrt}\) ...
- 【GWAS】如何计算显著关联位点的表型解释率PVE(phenotypic variation explained)?
我已经通过Gemma得到了关联分析的结果,如下. prefix.log.txt 中包含了一个总的PVE,这不是我们想要的. 那么,如何计算这些位点的表型解释率? 据了解,有些关联分析软件是可以同时得到 ...
- 【机器学习与R语言】6-线性回归
目录 1.理解回归 1)简单线性回归 2)普通最小二乘估计 3)相关系数 4)多元线性回归 2.线性回归应用示例 1)收集数据 2)探索和准备数据 3)训练数据 4)评估模型 5)提高模型性能 1.理 ...
- 学习java 7.25
学习内容: 特殊边框 1. TitledBorder:它的作用并不是直接为其他组件添加边框,而是为其他边框设置标题,创建该类的对象时,需要传入一个其他的Border对象; 2. CompoundBor ...
- 零基础学习java------day10------带包编译,权限修饰符,内部类,调式,junitTest
0. 带包编译 解决使用notepad++编写的java类中如果有package的解决方案,如下代码 package com._51doit.test; class HelloWorld{ publ ...
- Swagger2异常 java.lang.NumberFormatException: For input string: ""
问题在访问swagger首页时报错: java.lang.NumberFormatException: For input string: "" at java.lang.Numb ...
- Maven 目录结构[转载]
转载至:http://www.cnblogs.com/haippy/archive/2012/07/05/2577233.html Maven 标准目录结构 好的目录结构可以使开发人员更容易理解项目, ...
- Linux学习 - 修改、查询文件内容
一.显示文件内容 cat [-n] [文件名] 正向显示 -n 显示行号 tac [文件名] 反向显示 more [文件名] 可实现分页显示 (空格)或(f) 翻页 (Enter) 换行 (q ...
- dom4j解析XML学习
原理:把dom与SAX进行了封装 优点:JDOM的一个智能分支.扩充了其灵活性增加了一些额外的功能. package com.dom4j.xml; import java.io.FileNotFoun ...