次短路
来源:互联网 发布:电视直播软件tv版 编辑:程序博客网 时间:2024/06/10 03:58
顾名思义: 求出这幅图中某点到某点的次短路. 怎么求了?
利用Dijkstra算法求解次短路
我们曾经学过利用Dijkstra算法求解最短路, 但是如果要求解某一个结点的次短路该怎么做呢?实际上,我们仍然可以用Dijkstra算法来求解它.
首先来回顾一下Dijkstra算法的原理: 首先把所有结点的最短距离设置为无穷大, 然后令d[1] = 0. (到其本身) 接下来,每次都找到最短路已经确定的经典, 更新从它出发的相邻结点的最短距离. 以后我们不再考虑最短距离已经确定了的结点.
以上就是Dijkstra算法的主要过程, 需要注意的一点是我们不再考虑的是 “最短距离已经确定了的结点”, 不要错误地理解为是更新过最短距离值的结点. 因为有些结点的最短路可能需要多次更新才能最终确定. 那么问题来了, 如何知道哪些结点的最短距离是确定的呢? 这里我们利用了一点贪心的思想, 每次都取出当前距离最短的那个结点, 认为它的最短路就是已经确定好的. 可以证明这样的做法是正确的. 这也算为什么优化版本的Dijkstra算法用到了priority_queue的原因.
所以次短路的做法就是:
其实总的做法是一样的, 唯一的不同点在于, 在求出最短路径的情况下必须要保留下次短路径。对于Dijkstra判断中取出的每一个点, 如果到它的距离大于当前该点的次短距离, 则当前该点已经取到最短距离和次短距离,不进行操作, 否则进行两次判断: 如果小于最短边, 则赋给最短边, 并将最短边赋给次短边;或者如果大于最短边且小于次短边, 则赋给次短边. 两次完成之后均要加入队列. 要注意几点:
1 : 储存的是双向边, 那么结构体应该开大2倍.
2 : 进入第一个if语句时, 不应该直接赋值而是要swap !!! 因为最短边被修改后,它的值是要留给次短边的.
板子: (边权大一点的也适用) 其实也是可以求出最短路, 相当于堆优化了的Dij.
//这个板子只适用于求单源次短路, 最短路.
/** @Cain*/#define ll long long inttypedef pair<ll,int>P;const ll INF = 1e18;const int maxn = 1e5 + 5;int cas = 1;int head[maxn];ll dis1[maxn],dis2[maxn];int n,m,cnt;struct node{ int to,next; ll w;}s[maxn*2]; //两倍.void add(int u,int v,ll w){ s[cnt].to = v; s[cnt].w = w; s[cnt].next = head[u]; head[u] = cnt++;}void solve(){ while(~scanf("%d%d",&n,&m)){ cnt = 0; Fill(head,-1); Fill(s,0); for(int i=1;i<=m;i++){ int u,v; ll w; scanf("%d%d%lld",&u,&v,&w); add(u,v,w); add(v,u,w); } priority_queue<P, vector<P>, greater<P> >q; for(int i=1;i<=n;i++) dis1[i] = dis2[i] = INF; dis1[1] = 0; //次短路的初值就保持为无穷大. q.push(P(0,1)); while(!q.empty()){ P tmp = q.top(); q.pop(); ll d = tmp.first; int u = tmp.second; if(d > dis2[u] ) continue; //说明u点的最短路径和次短路径已经被更新过了. 不用重复操作. for(int i=head[u]; ~i ; i = s[i].next){ int to = s[i].to; ll d2 = d + s[i].w; if(dis1[to] > d2){ swap(dis1[to],d2); //不能直接赋值,而是要交换,因为原先的最短路值是要留着来更新次短路值的. //随便举一举例子就知道了.当然在这里判一下也是可以的,就可以直接赋值了. q.push(P(dis1[to],to)); } if(dis2[to] > d2 && dis1[to] < d2){ dis2[to] = d2; q.push(P(dis2[to],to)); } } } printf("%lld\n",dis2[n]); }}
POJ – 3255 模板题
AC Code
/** @Cain*/#define ll long long inttypedef pair<ll,int>P;const ll INF = 1e18;const int maxn = 1e5 + 5;int cas = 1;int head[maxn];ll dis1[maxn],dis2[maxn];int n,m,cnt;struct node{ int to,next; ll w;}s[maxn*2];void add(int u,int v,ll w){ s[cnt].to = v; s[cnt].w = w; s[cnt].next = head[u]; head[u] = cnt++;}void solve(){ while(~scanf("%d%d",&n,&m)){ if(n +m == 0) break; cnt = 0; Fill(head,-1); Fill(s,0); for(int i=1;i<=m;i++){ int u,v; ll w; scanf("%d%d%lld",&u,&v,&w); add(u,v,w); add(v,u,w); } priority_queue<P, vector<P>, greater<P> >q; for(int i=1;i<=n;i++) dis1[i] = dis2[i] = INF; dis1[1] = 0; q.push(P(0,1)); while(!q.empty()){ P tmp = q.top(); q.pop(); ll d = tmp.first; int u = tmp.second; if(d > dis2[u] ) continue; for(int i=head[u]; ~i ; i = s[i].next){ int to = s[i].to; ll d2 = d + s[i].w; if(dis1[to] > d2){ swap(dis1[to],d2); q.push(P(dis1[to],to)); } if(dis2[to] > d2 && dis1[to] < d2){ dis2[to] = d2; q.push(P(dis2[to],to)); } } } printf("%lld\n",dis2[n]); }}
- 次短路
- 次短路
- 次短路
- 次短路
- 次短路
- 次短路
- 最短路 & 次短路
- poj3463 最短路+次短路
- 最短路及次短路
- 次短路与k短路
- hdu 3191 次短路
- POJ 3225 次短路
- 【次短路】赛跑
- 次短路--poj3255
- POJ3255 Roadblocks , 次短路
- POJ3255 Roadblocks(次短路)
- poj 3255(次短路)
- 次短路问题
- Python3 爬虫学习(一):urllib库的使用及简单的爬取
- 周中训练笔记2
- 密码学基础知识(学习笔记)
- Block-sparse RPCA 数学推导(最详细版)
- 计算 h-index (2)
- 次短路
- 获取list集合中重复的元素
- 网易 合唱团
- uuid 在nRFgo中的生成方法
- 【Mac】在Mac OS X下解决opencv与Python的No module named cv2问题
- stm32f4定时器基本应用
- 书本第四章编程练习
- Thymeleaf框架
- Spark基础-Scala提取器