次短路——Dijkstra
传送门
——在LYC大佬的帮助下过了这道题
思路:
LYC大佬的博客里已经讲得很清晰了,我只是提一下要点。
求次短路,主要考虑两个方面:
①在不重复走一条路的前提下,把最短路的其中一段替换为另一段。
②找出最短路中的最短的一条边,重复走两次。(走过来又走回去)
分别求出这两方面所能算出的次短路的值,取小的那一条就是答案。
补充:
①读入的边要开结构体存起来,后面枚举求次短路要使用。
②所谓枚举,就是找出从开始一条一条的读出边的两端点、权值。确定其是否在最短路上(即它的 左端点到源点的最短路+右端点到源点的最短路+自身的边权 是否等于最短路长度。(注意细节:要判断这条边的两端点到源点的最短路是否有重合部分,如下图。)

设d[ a ]为 a 到源点的最短路,d[ b ]为 b 到源点的最短路,很显然,两条最短路有重合的地方,就需要将 a 点与 b 点交换位置,使得两条最短路没有重合,才能将 a->b 的权值加入。
代码实现:
if(d1[x]+d2[y]>d1[y]+d2[x]) swap(x,y);
效果如下:

完整代码:
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<deque>
#include<set>
#include<map>
#include<vector>
#include<fstream>
using namespace std;
#define maxn 1000007
struct edge
{
int x,y,w;
}dd[maxn];
struct hh
{
int nex,to,dis;
}t[maxn];
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q1;
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q2;//正反两次最短路,两个小根堆
int n,m,cnt=,ans,mi;
int vis[maxn],d1[maxn],d2[maxn],head[maxn];
inline int read()
{
char kr=;
char ls;
for(;ls>''||ls<'';kr=ls,ls=getchar());
int xs=;
for(;ls>=''&&ls<='';ls=getchar())
{
xs=xs*+ls-;
}
if(kr=='-') xs=-xs;
return xs;
}
inline void add(int nex,int to,int w)
{
t[++cnt].nex=head[nex];
t[cnt].to=to;
t[cnt].dis=w;
head[nex]=cnt;
}
inline void dijkstra_first(int ww)
{
memset(d1,0x3f3f3f3f,sizeof(d1));
memset(vis,,sizeof(vis));
q1.push(make_pair(,ww));
d1[ww]=;
while(!q1.empty())
{
int u=q1.top().second;
q1.pop();
if(vis[u]) continue;
vis[u]=;
for(int v=head[u];v;v=t[v].nex)
{
if(d1[t[v].to]>d1[u]+t[v].dis&&!vis[t[v].to])
{
d1[t[v].to]=d1[u]+t[v].dis;
q1.push(make_pair(d1[t[v].to],t[v].to));
}
}
}
}
inline void dijkstra_second(int ww)
{
memset(d2,0x3f3f3f3f,sizeof(d2));
memset(vis,,sizeof(vis));
q2.push(make_pair(,ww));
d2[ww]=;
while(!q2.empty())
{
int u=q2.top().second;
q2.pop();
if(vis[u]) continue;
vis[u]=;
for(int v=head[u];v;v=t[v].nex)
{
if(d2[t[v].to]>d2[u]+t[v].dis&&!vis[t[v].to])
{
d2[t[v].to]=d2[u]+t[v].dis;
q2.push(make_pair(d2[t[v].to],t[v].to));
}
}
}
}//两次Dijkstra求正反最短路
int main()
{
n=read();m=read();
ans=;
mi=;
for(int i=;i<=m;++i)
{
dd[i].x=read();dd[i].y=read();dd[i].w=read();
add(dd[i].x,dd[i].y,dd[i].w);
add(dd[i].y,dd[i].x,dd[i].w);
}
dijkstra_first();
dijkstra_second(n);
int minn=d1[n];
for(int i=;i<=m;i++)
{
int x=dd[i].x,y=dd[i].y;
if(d1[x]+d2[y]>d1[y]+d2[x]) swap(x,y);
int s=d1[x]+d2[y];
if(s+dd[i].w==minn) continue;
ans=min(ans,s+dd[i].w);
}//第一点:不重走边
for(int i=;i<=m;i++)
{
int x=dd[i].x,y=dd[i].y;
if(d1[x]+d2[y]>d1[y]+d2[x]) swap(x,y);
if(d1[x]+d2[y]+dd[i].w!=minn) continue;
mi=min(mi,dd[i].w);//找出最短路中最短的边
}//第二点:重走边
ans=min(ans,minn+mi*);//取较小值
printf("%d\n",ans);
return ;
}
其实两遍的Dijkstra函数可以简化为一遍,多打一遍练练模板。
次短路——Dijkstra的更多相关文章
- hdu 2544 最短路 Dijkstra
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544 题目分析:比较简单的最短路算法应用.题目告知起点与终点的位置,以及各路口之间路径到达所需的时间, ...
- 算法学习笔记(三) 最短路 Dijkstra 和 Floyd 算法
图论中一个经典问题就是求最短路.最为基础和最为经典的算法莫过于 Dijkstra 和 Floyd 算法,一个是贪心算法,一个是动态规划.这也是算法中的两大经典代表.用一个简单图在纸上一步一步演算,也是 ...
- 单源最短路dijkstra算法&&优化史
一下午都在学最短路dijkstra算法,总算是优化到了我能达到的水平的最快水准,然后列举一下我的优化历史,顺便总结总结 最朴素算法: 邻接矩阵存边+贪心||dp思想,几乎纯暴力,luoguTLE+ML ...
- HUD.2544 最短路 (Dijkstra)
HUD.2544 最短路 (Dijkstra) 题意分析 1表示起点,n表示起点(或者颠倒过来也可以) 建立无向图 从n或者1跑dij即可. 代码总览 #include <bits/stdc++ ...
- 训练指南 UVALive - 4080(最短路Dijkstra + 边修改 + 最短路树)
layout: post title: 训练指南 UVALive - 4080(最短路Dijkstra + 边修改 + 最短路树) author: "luowentaoaa" ca ...
- 训练指南 UVA - 10917(最短路Dijkstra + 基础DP)
layout: post title: 训练指南 UVA - 10917(最短路Dijkstra + 基础DP) author: "luowentaoaa" catalog: tr ...
- 训练指南 UVA - 11374(最短路Dijkstra + 记录路径 + 模板)
layout: post title: 训练指南 UVA - 11374(最短路Dijkstra + 记录路径 + 模板) author: "luowentaoaa" catalo ...
- 最短路Dijkstra算法的一些扩展问题
最短路Dijkstra算法的一些扩展问题 很早以前写过关于A*求k短路的文章,那时候还不明白为什么还可以把所有点重复的放入堆中,只知道那样求出来的就是对的.知其然不知其所以然是件容易引发伤痛的 ...
- 华夏60 战斗机(最短路dijkstra)
华夏60 战斗机(最短路dijkstra) 华夏60 超音速战斗机是当今世界上机动性能最先进的战斗机.战斗过程中的一个关键问题是如何在最短的时间内使飞机从当前的飞行高度和速度爬升/俯冲到指定的高度并达 ...
- Til the Cows Come Home 最短路Dijkstra+bellman(普通+优化)
Til the Cows Come Home 最短路Dijkstra+bellman(普通+优化) 贝西在田里,想在农夫约翰叫醒她早上挤奶之前回到谷仓尽可能多地睡一觉.贝西需要她的美梦,所以她想尽快回 ...
随机推荐
- いろはちゃんとマス目 / Iroha and a Grid (组合数学)
题目链接:http://abc042.contest.atcoder.jp/tasks/arc058_b Time limit : 2sec / Memory limit : 256MB Score ...
- [转载]Oracle中的NVL函数
Oracle中函数以前介绍的字符串处理,日期函数,数学函数,以及转换函数等等,还有一类函数是通用函数.主要有:NVL,NVL2,NULLIF,COALESCE,这几个函数用在各个类型上都可以. 下面简 ...
- .NET 常用ORM之SubSonic
一.SubSonic简单介绍 SubSonic是一个类似Rails的开源.NET项目.你可以把它看作是一把瑞士军刀,它可以用来构建Website和通过ORM方式来访问数据.Rob Conery和Eri ...
- django项目----函数和方法的区别
一.函数和方法的区别 1.函数要手动传self,方法不用传 2.如果是一个函数,用类名去调用,如果是一个方法,用对象去调用 举例说明: class Foo(object): def __init__( ...
- 写出优质Java代码的4个技巧
我们平时的编程任务不外乎就是将相同的技术套件应用到不同的项目中去,对于大多数情况来说,这些技术都是可以满足目标的.然而,有的项目可能需要用到一些特别的技术,因此工程师们得深入研究,去寻找那些最简单但最 ...
- 关于web.xml中配置Spring字符编码过滤器以解决中文乱码的问题
当出现中文乱码问题,Spring中可以利用CharacterEncodingFilter过滤器解决,如下代码所示: <!-- Spring字符编码过滤器:解决中文乱码问题 --> < ...
- linux下启动多个php,分别监听不同的端口。
在工作中,我们可能会遇到,服务器集群的搭建. 这个时候,我们不可能,每一台服务器都是lnmp的环境,我们会把nmp分别放在不同的服务器上,不同的服务器负责不同的功能.比如我们下面要说的php 加入ng ...
- Leetcode480-Sliding Window Median
Median is the middle value in an ordered integer list. If the size of the list is even, there is no ...
- 通过注册表regedit对Windows回收站进行恢复
误删资料恢复 一不小心,删错了,还把回收站清空了,咋办啊? 只要三步,你就能找回你删掉并清空回收站的东西 步骤: 1.单击"开始——运行,然后输入regedit(打开注册表) 2.依次展开: ...
- [内核驱动] VS2012+WDK 8.0 Minifilter实现指定扩展名文件拒绝访问
转载:http://blog.csdn.net/C0ldstudy/article/details/51585708 转载:http://blog.csdn.net/zj510/article/det ...