【Dijkstra+邻接表求次短路】POJ Sightseeing 3463
|
Language:
Default
Sightseeing
Description Tour operator Your Personal Holiday organises guided bus trips across the Benelux. Every day the bus moves from one city S to another city F. On this way, the tourists in the bus can see the sights Different groups of tourists may have different preferences for the sights they want to see, and thus for the route to be taken from S to F. Therefore, Your Personal Holiday wants to offer its clients There is a restriction on the routes that the tourists may choose from. To leave enough time for the sightseeing at the stops (and to avoid using too much fuel), the bus has to take a short route from S to F. ![]() For example, for the above road map, there are two minimal routes from S = 1 to F = 5: 1 → 2 → 5 and 1 → 3 → 5, both of length 6. There is one route that is one distance unit longer: 1 Now, given a (partial) road map of the Benelux and two cities S and F, tour operator Your Personal Holiday likes to know how many different routes it can offer to its clients, under the above restriction Input The first line of the input file contains a single number: the number of test cases to follow. Each test case has the following format:
Output For every test case in the input file, the output should contain a single number, on a single line: the number of routes of minimal length or one distance unit longer. Test cases are such, that this number is at most 109 = 1,000,000,000. Sample Input 2 Sample Output 3 Hint The first test case above corresponds to the picture in the problem description. Source |
题意:
旅行团从S地出发到达T地。为了省油要求尽量走最短路径或比最短路径长1单位距离的路径。求满足条件的路径条数
解题思路:
相信最短路非常easy求出来的,主要是次短路怎样求出???
我们能够先求出从S到T的次短路的距离。然后推断这个距离与最短距离是否相差为一?所以我们的任务就变成了求解次短路和最短路的问题。
(s。u,v)代表从s——v的最短路,u是中间一个必经点。
我们先看看最短路和次短路的比較:
①(s,u,v)最短路=到达前一个点u的最短路+(u。v)的最短路。
而最短路求解有两种情况:
①(s。u。v)次短路=到达前一个点u的次短路+(u。v)的最短路。
②(s,u,v)次短路=到达前一个点u的最短路+(u,v)的次短路。
所以根据次短路的求解条件。能够在求解最短路的时候求解次短路。
我们用:d[ v ][ 0 ]代表最短路,d[ v ] [ 1 ]代表次短路。
(一)假设从s—u的最短路加上(u,v)权值的距离小于原来的d[ v ][ 0 ] ,我们就可把次短路d[ v ][ 1 ] 的值更新为d[ v ][ 0 ]。就该题而言,此时能够把次短路的条数也更新为这个点的最短路的条数;把当前最短路d[ v ][ 0 ]的值更新成最小的,和原来最短路的松弛操作是一样的。
(二)假设从s—u的最短路加上(u。v)权值的距离大于原来的d[ v ][ 0 ],这就说明这条路路径就可能是一条次短路,那我们须要推断这条路的值dist。和原来的次短路的值d[ v ][1]进行比較!
①假设它比原来的次短路要大,直接跳过。
②假设它比原来的次短路要小,那么我们就须要更新最短路的长度。
③假设与原来的次短路相等。说明我们的次短路有还有一种(这里并不一定是仅仅有1种)方法能够到达终点v。这里要加的种类是:原来到v点的次短路的条数+到u点的次短路(或者最短路。(u。v)并不知道是不是一定是最短路,假设是次短路,那么此时加的就是到u的最短路)的条数。
次短路的情况已经分析出来,最短路的情况是比較easy得出了的。和Dijkstra操作正常的松弛操作就能够了。只是本题让求路径条数。所以要在松弛操作出现相等情况时进行相加操作。这一点比較简单,不在分析,具体看代码。
AC代码:
#include <stdio.h>
#include <math.h>
#include <vector>
#include <queue>
#include <string>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
#define INF 0x3f3f3f3f using namespace std; const int MAXN = 10010;
const int MAXM = 100010; struct Edge
{
int from;
int to;
int w;
int next;
}edge[MAXN]; int tot;
int head[MAXM]; void addEdge(int u,int v,int w)
{
edge[tot].from=u;
edge[tot].to=v;
edge[tot].w=w;
edge[tot].next=head[u];
head[u]=tot++;
} int d[MAXM][2];//记录最短路、次短路距离。 int c[MAXN][2];//记录最短路、次短路路径条数。
int vis[MAXN][2];//记录最短路、次短路时该点是否被訪问过。
int N,M; void Dijkstra(int s)
{
int flag;
int k;
for(int i=1;i<=N;i++){
c[i][0]=c[i][1]=0;
d[i][0]=d[i][1]=INF;
vis[i][0]=vis[i][1]=0;
}
d[s][0]=0;
c[s][0]=1;
int min_dist=INF;
while(true){
int v=-1;
for(int i=1;i<=N;i++){ //我们并不能确定取出的最小值的就一定是最短路的点
for(int j=0;j<2;j++){//所以要遍历次短和最短的点。
if(!vis[i][j]&&(v==-1||d[i][j]<d[v][k])){
v=i;
k=j;//记录这个点是次短还是最短
}
}
}
if(v==-1) break;
vis[v][k]=1;
for(int i=head[v];i!=-1;i=edge[i].next){
int j=edge[i].to;
int dist=d[v][k]+edge[i].w;;
if(dist<d[j][0]){//dist小于最短路径长。 d[j][1]=d[j][0];//次短路径长
c[j][1]=c[j][0];//次短路径路径数目
d[j][0]=dist;//最短路径长
c[j][0]=c[v][k];//最短路径路径数目
}
else if(dist==d[j][0]){//dist等于最短路径长:
c[j][0]+=c[v][k];//最短路径路径数目
}
else if(dist<d[j][1]){//dist大于最短路径长且小于次短路径长:
d[j][1]=dist;//次短路径长
c[j][1]=c[v][k];//次短路径路径数目
}
else if(dist==d[j][1]){//dist等于次短路径长:
c[j][1]+=c[v][k];//次短路径路径数目
}
}
}
} int main()
{
int t;
scanf("%d",&t);
while(t--){
tot=0;
memset(head,-1,sizeof(head));
scanf("%d%d",&N,&M);
int u,v,w;
for(int i=0;i<M;i++){
scanf("%d%d%d",&u,&v,&w);
addEdge(u,v,w);
}
int s,g;
scanf("%d%d",&s,&g);
Dijkstra(s);
int res=c[g][0];
if(d[g][1]==d[g][0]+1){
res+=c[g][1];
}
printf("%d\n",res);
}
return 0;
}
【Dijkstra+邻接表求次短路】POJ Sightseeing 3463的更多相关文章
- POJ - 3255 SPFA+邻接表求次短路径
题意:给出m条边 , n个顶点,u [ i ]到v [ i ] 的距离w [ i ],求除了最短路的那条最短的边的长度. 思路:之前有做过相似的题,使用迪杰斯特拉算法求单源最短路径,并且记录路径,枚举 ...
- E - Easy Dijkstra Problem(求最短路)
Description Determine the shortest path between the specified vertices in the graph given in the inp ...
- Floyd && Dijkstra +邻接表 +链式前向星(真题讲解来源:城市路)
1381:城市路(Dijkstra) 时间限制: 1000 ms 内存限制: 65536 KB提交数: 4066 通过数: 1163 [题目描述] 罗老师被邀请参加一个舞会,是 ...
- HDU 1688 Sightseeing&HDU 3191 How Many Paths Are There(Dijkstra变形求次短路条数)
Sightseeing Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- HDOJ 2544 最短路(最短路径 dijkstra算法,SPFA邻接表实现,floyd算法)
最短路 Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submis ...
- USACO 2008 January Silver Telephone Lines /// 二分最短路 邻接表dijkstra oj22924
题目大意: 一共有N (1 ≤ N ≤ 1,000)个电线杆,有P P (1 ≤ P ≤ 10,000)对电线杆是可以连接的, 用几条线连接在一起的电线杆之间都可相互通信,现在想要使得电线杆1和电线杆 ...
- HDU 1874 畅通工程续(最短路/spfa Dijkstra 邻接矩阵+邻接表)
题目链接: 传送门 畅通工程续 Time Limit: 1000MS Memory Limit: 65536K Description 某省自从实行了很多年的畅通工程计划后,终于修建了很多路. ...
- POJ 1511 - Invitation Cards 邻接表 Dijkstra堆优化
昨天的题太水了,堆优化跑的不爽,今天换了一个题,1000000个点,1000000条边= = 试一试邻接表 写的过程中遇到了一些问题,由于习惯于把数据结构封装在 struct 里,结果 int [10 ...
- POJ - 3037-Skiing(邻接表+Dijkstra)
Bessie and the rest of Farmer John's cows are taking a trip this winter to go skiing. One day Bessie ...
随机推荐
- 81.内存模式实现cgi查询
创建全局的二级指针 char ** g_pp;//全局的二级指针 获取数据有多少行 //获取行数 int getimax() { ; FILE *pf = fopen(path, "r&qu ...
- visual studio code 中 debugger for chrome 插件的配置
安装 debugger for chrome 插件后,把默认的 launch.json 改成: { "name": "谷歌浏览器", "type&qu ...
- AsyncCallback BeginInvode endinvode 异步调用
下面是搜藏的代码: //首先准备好,要进行C#异步调用的方法(能C#异步调用的,最好不多线程) private string MethodName(int Num, out int Num2) { N ...
- Altium Designer如何调整鼠标形状
在 里面有一个
- jmeter--函数助手对话框之参数详解
详解JMeter函数和变量 测试人员可以在JMeter的选项菜单中找到函数助手对话框("Function Helper"对话框),如图11-1所示. 图11-1 函数助手(Func ...
- Windows下安装Resin及配置具体解释与公布应用
关于Resin的优点,网上介绍了一大堆.小编经不住诱惑,决定试用一下. 眼下Resin的最新版本号为:4.0.40.能够从官网直接下载. 1. 将下载下来的Resin包解压开,会看到一 ...
- 数据结构-堆实现优先队列(java)
队列的特点是先进先出.通常都把队列比喻成排队买东西,大家都非常守秩序,先排队的人就先买东西. 可是优先队列有所不同,它不遵循先进先出的规则,而是依据队列中元素的优先权,优先权最大的先被取出. 这就非常 ...
- 10.2、android输入系统_必备Linux编程知识_双向通信(scoketpair)
2. 双向通信(socketpair) 输入系统肯定涉及进程通讯:进程A读取/分发输入事件,APP处理输入事件,进程A给APP发送输入事件,APP处理完事件回复信息给进程A,APP关闭的时候也要发信息 ...
- 如何获取AppStore软件安装包的路径
本帖最后由 chinald 于 2015-10-16 13:59 编辑 前言:本文介绍在Mac下如何找到AppStore下载的安装包路径,以及如何提取出来供以后使用,希望对大家有所帮助(前提:想要提取 ...
- 【Codeforces Round #437 (Div. 2) B】Save the problem!
[链接]h在这里写链接 [题意] 给你一个金额N,和硬币的类型总数M; (完全背包),然后问你组成N的方案数. 使得,用这些硬币组成价值为N的金额的方案数为A; 现在A ...
