【dijkstra优化/次短路径】POJ3255-Roadblocks
【题目大意】
给出一张无向图,求出从源点到终点的次短边。
【思路】
先来谈谈Dijkstra的优化。对于每次寻找到当前为访问过的点中距离最短的那一个,运用优先队列进行优化,避免全部扫描,每更新一个点的最短距离就加入优先队列。有人会问,一个点如果已经处理完成了,那它还留在队列中怎么办?我们放入队列时将一个点那时的顶点编号和最短距离进行打包,如果取出该点时,它当前的最短距离小于该点标记的最短距离,说明该点已经取到最短距离,不进行操作。或者直接用一个vis数组来记录某一个点是否已经取到最短距离;其次的优化是用邻接表存储与每一个点相连的所有边,方便处理。
这道题的做法和最短路径基本一致,唯一的不同点在于,在求出最短路径的情况下必须要保留下次短路径。对于Dijkstra判断中取出的每一个点,如果到它的最短距离大于当前该点的次短距离,则当前该点已经取到最短距离和次短距离,不进行操作,否则进行两次判断:如果小于最短边,则赋给最短变,并将最短边赋给次短边;或者如果大于最短变且小于次短边,则赋给次短边。两次完成之后均要加入队列。要注意几点:
(1)由于是一张无向图,读入的时候必须正向、逆向分为两条边存储,所以实际有向边的数量为r的两倍,数组绝对不能开小!我就因为这个错拿了90分,还检查了三个小时后找到测试数据才意识到的...
(2)初始化时,源点的短边初始化为0,源点的次短边必须初始化为INF,而不是0。比如下面这组数据:
4 2
1 2 100
2 4 200
答案应该是500,然而如果初始化为0则答案会输出700。因为500的结果是又1到2,在从2返回1,再到2,再到4,100+100+100+200=500得到的;如果次短边初始化为0,则次短路径不再返回源点,而是在2与4之间折返,会偏大。
(3)53行绝对不能直接赋值,而是要swap!因为最短边被修改后,它的值是要留给次短边的。
2015.09.06温习时候的补充
(1)要注意if (head.len>secondis[head.num]) continue;的位置!我两次写的时候都把它放在了while(k!=-1)里面然后判断(d>secondis[v[k]])这是不对的!因为如果这个时候continue,k的值就无法改变,会导致死循环。
(2)要注意优先队列默认是大顶堆,struct里面设置的时候前后大于小于号必须要相反才能设置成小顶堆!
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdlib>
using namespace std;
const int INF=0x7fffffff;
const int MAXN=+;
struct Rec
{
int num,len;
bool operator < (const Rec &a) const
{
return len>a.len;
/*优先队列强制设为以len为关键词的小顶堆*/
}
};
int u[MAXN*],v[MAXN*],w[MAXN*];
/*依次表示每条道路的起点、终点和长度*/
int dis[MAXN/],secondis[MAXN/];
/*记录通往每一个路口的最短和次短距离*/
int first[MAXN/],next[MAXN*];
int n,r; void dijkstra()
{
priority_queue<Rec> que; for (int i=;i<n;i++)
{
dis[i]=INF;
secondis[i]=INF;
}
dis[]=;
secondis[]=INF; Rec temp;
temp.len=;temp.num=;
que.push(temp); while (!que.empty())
{
Rec head=que.top();
que.pop();
if (head.len>secondis[head.num]) continue; int k=first[head.num];
while (k!=-)
{
int d=head.len+w[k];
if (dis[v[k]]>d)
{
swap(dis[v[k]],d);
temp.len=dis[v[k]];temp.num=v[k];
que.push(temp);
}
if (dis[v[k]]<d && secondis[v[k]]>d)
{
secondis[v[k]]=d;
temp.len=secondis[v[k]];temp.num=v[k];
que.push(temp);
}
k=next[k];
}
}
} int main()
{
scanf("%d%d",&n,&r);
memset(first,-,sizeof(first));
for (int i=;i<r;i++)
{
scanf("%d%d%d",&u[i],&v[i],&w[i]);
u[i]--;
v[i]--;
next[i]=first[u[i]];
first[u[i]]=i; v[i+r]=u[i];
u[i+r]=v[i];
w[i+r]=w[i];
next[i+r]=first[u[i+r]];
first[u[i+r]]=i+r;
}
dijkstra();
cout<<secondis[n-]<<endl;
return ;
}
【dijkstra优化/次短路径】POJ3255-Roadblocks的更多相关文章
- POJ 3255 Roadblocks (Dijkstra求最短路径的变形)(Dijkstra求次短路径)
Roadblocks Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 16425 Accepted: 5797 Descr ...
- POJ3255(Roadblocks)--次短路径
点这里看题目 3228K 485MS G++ 2453B 根据题意和测试用例知道这是一个求次短路径的题目.次短路径,就是比最短路径长那么一丢丢的路径,而题中又是要求从一点到指定点的次短路径,果断Dij ...
- 【次短路径/SPFA】BZOJ1726-[Usaco2006 Nov]Roadblocks第二短路
[题目大意] 求无向图点1到n的次短路. [思路] 一年多前写过一次堆优化Dijkstra的,方法就是一边跑Dijsktra一边就把次短路径保存下来.和一般Dijkstra不同的是把vis数组去掉了, ...
- hdu-3790-最短路径问题(Dijkstra)
题目链接 /* Name:hdu-3790-最短路径问题 Copyright: Author: Date: 2018/4/16 19:16:25 Description: dijkstra 模板题 * ...
- POJ - 3255 次短路径
题意:给你无向带权图,求次短路径 题解:加一个次短路的数组,用于距记录源点到此点的次短路长度,注意初始化是源点到自己的次短路是极大值 接着再使用dijkstra算法,它是每次选用现在连上(记录了)的点 ...
- A* 算法求第k短路径
A*算法是一类贪心算法,其可以用于寻找最优路径.我们可以利用A*算法来求第k短路径. 一条路径可以由两部分组成,第一部分是一个从出发到达任意点的任意路径,而第二部分是从第一部分的末端出发,到终点的最短 ...
- hdu 3191 How Many Paths Are There (次短路径数)
How Many Paths Are There Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java ...
- 单源次短路径:poj:3255-Roadblocks
Roadblocks Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 17521 Accepted: 6167 Descripti ...
- POJ3255 Roadblocks 严格次短路
题目大意:求图的严格次短路. 方法1: SPFA,同时求单源最短路径和单源次短路径.站在节点u上放松与其向量的v的次短路径时时,先尝试由u的最短路径放松,再尝试由u的次短路径放松(该两步并非非此即彼) ...
随机推荐
- 【四校联考】【比赛题解】FJ NOIP 四校联考 2017 Round 7
此次比赛为厦门一中出题.都是聚劳,不敢恭维. 莫名爆了个0,究其原因,竟然是快读炸了……很狗,很难受. 话不多说,来看看题: [T1] 题意: 样例: PS:1<=h[i]<=100000 ...
- SQL 根据关联表更新主表中字段数据
今天遇到一个客户的数据更新问题,两个相关联的表,一个主表用于保存单据主要信息,一个副表用于保存单据的明细信息:现在要把主表的其中一个字段的数据更新到副表的一个字段中保存.精通的SQL语法的,当然是很简 ...
- STM8CubeMx来了
几年前出来的STM32CubeMx是众多stm32开发者的福音,大大缩短了开发者的开发周期.就在前几天,st官网宣布针对stm8的图形配置工具stm8cube横空出世. 如果你还不知道STM32Cub ...
- Spark RDD 窄依赖研究
1.. 简介 spark从RDD依赖上来说分为窄依赖和宽依赖. 其中可以这样区分是哪种依赖:当父RDD的一个partition被子RDD的多个partitions引用到的时候则说明是宽依赖,否则为窄依 ...
- JS动态创建元素(两种方法)
前言 创建元素有两种方法 1)将需要创建的元素,以字符串的形式拼接:找到父级元素,直接对父级元素的innnerHTML进行赋值. 2)使用Document.Element对象自带的一些函数,来实现动态 ...
- Linux学习笔记:ps -ef、ps aux、kill -9
一.查看进程命令 1.ps命令 Linux中的ps命令是Process Status的缩写. ps命令用来列出系统中当前运行的那些进程. ps命令列出的是当前那些进程的快照,就是执行ps命令的那个时刻 ...
- 浅谈DDD
从遇到问题开始 当人们要做一个软件系统时,一般总是因为遇到了什么问题,然后希望通过一个软件系统来解决. 比如,我是一家企业,然后我觉得我现在线下销售自己的产品还不够,我希望能够在线上也能销售自己的产品 ...
- #JS Ajax的error函数
使用jquery的ajax方法向服务器发送请求的时候,常常需要使用到error函数进行错误信息的处理, 一般error函数返回的参数有三个: function(jqXHR jqXHR, String ...
- 从字节码角度分析Byte类型变量b++和++b
1. 下面是一到Java笔试题: public class Test2 { public void add(Byte b) { b = b++; } public void test() { Byte ...
- 解决Python爬虫使用requests包控制台输出乱码问题
输出爬取的信息为乱码! 解决办法 爬取下来的编码是ISO-8859-1格式,需要转化为utf-8格式,加一句response.encoding = "utf8"