最短路径问题小结

最短路径问题包括:

1、单源最短路。

2、任意两点间的最短路。

3、次短路和k短路。

4、差分约束系统。

5、DAG图上的单源最短路。

6、最小环。

一、单源最短路

算法: Dijkstra 、 Bellman - Ford 、SPFA

Dijkstra: 除了路径记录和更新距离数组的部分意外,和Prim算法的实现完全一样。使用邻接矩阵建图,时间复杂度为O(n*n)。使用邻接表可能会快一些。堆优化比较麻烦,没学。缺点是图中不能含有负圈。

Bellman - Ford :可以处理负圈。以链式前向星建图,时间复杂度为O (n*m)。

SPFA: 优化的Bellman - Ford算法,可以处理负圈。期望的时间复杂度为O(k*m),k<=2。普遍认为其效率高于朴素的Dijkstra,低于堆优化的Dijkstra。

题目:

多源转单源  hdu2066一个人的旅行

来回最短路(有向图) 建反向图  hdu1535Invitation Cards

有限制的最短路   hdu3873Invade the Mars

二分法求带限制的最短路  hdu2962 Trucking

(综合题)强连通+最短路 poj3114

二、任意两点间的最短路

解决的问题:给出一幅图(有向或者无向),有多次询问,问任意两点之间的最短距离是多少。

暴力的方法:运行多次最短路算法。一般这种题目的数据量大,此算法复杂度太高,不适用。

Floyd算法:邻接矩阵建图,三重循环,时间复杂度为O(n*n*n)。

提醒:初学者一般会把算法混淆。比如说,把这种题目理解为LCA问题,然后用离线的Tarjan算法来做,时间复杂度是O(m+q),不是更快么?需要知道的是LCA问题是指树的最近公共祖先,其解题范围是树。对于有环的图是无能为力的。

题目:

输出最短路的路径(字典序最小)  hdu1385Minimum Transport Cos    传送门:http://www.cnblogs.com/Potato-lover/p/3959795.html

三、次短路和k短路

字面上看次短就是第二路边,归结到K短路就可以了。实现却不能这样做,原因是算法的实现不能这样做。说到底还是时间复杂度的问题。

次短路是通过修改Dijkstra算法而实现的。时间复杂度是O(n*n)。

K短路是通过SPFA+A*实现的。如果只求K短路的值效率挺高的,但是如果要求与K短路值相同的路径有多少条,这个就很复杂了。

暴力的方法:求一遍最短路,记录路径并记录任意两点之间的路径之间的最大边,枚举所有边。(类似与Prim暴力求次小生成树)。

下面是K短路的实现:

SPFA + A* 实现K短路

K短路要用到A*算法,A*算法通过一个估价函数f(h)来估计途中的当前点p到终点的距离,并由此决定它的搜索方向,当这条路径失败时,它会尝试其他路径。对于A*,估价函数 = 当前值 + 当前位置到终点的距离, 即f (p) = g (p) + h (p) ,每次扩展估计函数值最小的一个。对于K短路算法来说,g (p) 为当前从s到p所走的路径的长度,h (p)为从点p到t的最短路的长度,则f (p)的意义就是从s按照当前路径走到p后再走到终点t一共至少要走多远。

具体实现步骤:

使用链式前向星来存储图, 由于需要预处理所有的点到终点T的最短路径,就需要将图G中所有的边反响得到G1再从终点T做单源最短路径,所以实际上是两张图。

1、将有向图的所有边反向。以T(终点)为源点,求解T到所有点的最短距离。这一步可以用Dijkstra 或者 SPFA算法。我用的是 SPFA(shortest  path  faster  algorithm)。

2、新建一个优先队列,将源点S加入到队列中。

3、从优先队列中弹出f (p)最小的p,如果点p就是t ,则计算t出队的次数,如果当前为T的第K次出队,则当前路径的长度就是s到t的第K短路的长度,算法结束。否则,遍历与p项链的所有的边,将扩展出的到p的邻接点信息加入到优先队列。

注意:当s = =t时需要计算K+1短路,以为s到t这条距离为0的路不能算在这K短路中,这时只需将K加1后再求第K短路即可。

题目:

次短路 hdu3191  hdu1688

K短路 poj2499

国界传送门:http://www.cnblogs.com/wally/archive/2013/04/16/3024490.html

四、差分约束系统

我已经做出总结。 传送门:http://www.cnblogs.com/Potato-lover/p/3959979.html

五、DAG图上的单源最短路

伪代码:

1、初始化,入度为0的结点dist为0,其他的结点的dist为INF。

2、对DAG进行拓扑排序,得到拓扑序列。

3、按照拓扑序列遍历DAG的点,对于每个点u,遍历其所有的出边<u,v>,如果dist[v] > dist[u ] + Map[u][v],那么dist[v] > dist[u ] + Map[u][v]。

此方法可以处理负权边。

题目: poj3249

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6
 7 const int N = 100010, M =1100010, INF=0x3f3f3f3f;
 8 struct node
 9 {
10     int to, w, next;
11 };
12 node edge[M];
13 int ind[N], head[N], dist[N], que[N], cost[N];
14 //Èë¶È
15 int iq, ans;
16 void topo(int n)
17 {
18     int i,k;
19     iq=0;
20     memset(que,0,sizeof(que));
21     for(i=1;i<=n;i++)
22         if(ind[i]==0) que[iq++]=i;
23     for(i=0;i<iq;i++)
24     {
25         for(k=head[que[i]]; k!=-1; k=edge[k].next)
26         {
27             ind[edge[k].to]--;
28             if(ind[edge[k].to]==0)
29                 que[iq++]=edge[k].to;
30         }
31     }
32 }
33 void DAG(int n)
34 {
35     int i,k;
36     ans=-INF;
37     for(i=1;i<=n;i++) dist[i]=-INF;// -INF
38     dist[n]=0;
39     for(i=0;i<iq;i++)
40     {
41         int flag=1;
42         for(k=head[que[i]];k!=-1;k=edge[k].next)
43         {
44             flag=0;
45             if(dist[edge[k].to]<dist[que[i]] + edge[k].w)
46                 dist[edge[k].to]=dist[que[i]] + edge[k].w;
47         }
48         if(flag) ans=max(ans,dist[que[i]]);
49     }
50 }
51 void addedge(int i,int j,int k,int w)
52 {
53     edge[k].to=j;
54     edge[k].w=w;
55     edge[k].next=head[i];
56     head[i]=k;
57 }
58 int main()
59 {
60     //freopen("test.txt","r",stdin);
61     int n,m,i,j,k,t;
62     while(scanf("%d%d",&n,&m)!=EOF)
63     {
64         memset(head,-1,sizeof(head));
65         memset(ind,0,sizeof(ind));
66         for(i=1;i<=n;i++) scanf("%d",&cost[i]);
67         for(k=0;k<m;k++)
68         {
69             scanf("%d%d",&i,&j);
70             ind[j]++;
71             addedge(i,j,k,cost[j]);
72         }
73         for(i=1;i<=n;i++)
74             if(ind[i]==0)
75             {
76                 ind[i]=1;
77                 addedge(n+1,i,k++,cost[i]);
78             }
79         topo(n+1);
80         DAG(n+1);
81         printf("%d\n",ans);
82     }
83     return 0;
84 }

六、最小环

用Floyd求最小环

Poj1734 Sightseeing trip

Hdu1599

传送门:http://www.cnblogs.com/Potato-lover/p/3954124.html

时间: 2024-10-10 22:25:33

最短路径问题小结的相关文章

最短路径算法小结

不同性质的图中,所采取的策略有所不同,自然存在各样的求最短路径的算法. 无向无权图:BFS 有向正权图:Dijkstra 有向无负环图:Bellman-Ford(单点),Floyd-Warshall(任意两点) 有向无环图(dags): 基于动态规划的算法. 广度优先搜索(BFS) 对于无向无权图(也可以假设权值为1),就可以使用最基本的广度优先搜索算法,从源点开始对整个图进行搜索,访问到所有的点.因为广度优先搜索最先访问到的是相邻的点,所以距离最近的点最先访问到,记录的距离也就最小. 算法伪代

单源最短路径小结

一.负权问题 如果一个图仅仅是存在负权,但不构成负权回路,又该如何? Dijkstra 算法 观察上图,若 A 作为源点,在第一轮循环后,B 被标记数组标记,但我们发现在第二轮循环中,B 还可以通过 C 点继续进行更新.由此,可以得出结论:Dijkstra 算法不适用于负权图. Bellman_Ford 算法和 SPFA 算法 我们先思考下上述 "因 B 点被标记数组标记而导致无法通过 C 点再更新" 的问题,归根结底是标记数组的锅.有人提议,不妨去掉标记数组,如果去掉,就会造成很严重

Dijkstra算法求单源最短路径

1.最短路径 在一个连通图中,从一个顶点到另一个顶点间可能存在多条路径,而每条路径的边数并不一定相同.如果是一个带权图,那么路径长度为路径上各边的权值的总和.两个顶点间路径长度最短的那条路径称为两个顶点间的最短路径,其路径长度称为最短路径长度. 最短路径在实际中有重要的应用价值.如用顶点表示城市,边表示两城市之间的道路,边上的权值表示两城市之间的距离.那么城市A到城市B连通的情况下,哪条路径距离最短呢,这样的问题可以归结为最短路径问题. 求最短路径常见的算法有Dijkstra算法和Floyd算法

在SQL Server实现最短路径的搜索

开始 这是去年的问题了,今天在整理邮件的时候才发现这个问题,感觉顶有意思的,特记录下来. 在表RelationGraph中,有三个字段(ID,Node,RelatedNode),其中Node和RelatedNode两个字段描述两个节点的连接关系:现在要求,找出从节点"p"至节点"j",最短路径(即经过的节点最少). 图1. 解析 为了能够更好的描述表RelationGraph中字段Node和 RelatedNode的关系,我在这里特意使用一个图形来描述,如图2. 图

搜索专题小结及例题:POJ2251&amp;POJ1426&amp;POJ3087&amp;POJ2488

图的遍历也称为搜索,就是从图中某个顶点出发,沿着一些边遍历图中所有的顶点,且每个顶点仅被访问一次,遍历可采取两种不同的方式:深度优先搜索(DFS)和广度优先搜索(BFS). 1.DFS算法思想` 从顶点v出发深度遍历图G的算法 ① 访问v0顶点,置vis[v0]=1,搜索v0未被访问的邻接点w,若存在邻接点w,则dfs(w),直到到达所有邻接点都被访问过的顶点u为止,接着退回一步,看是否还有其他没有被访问的邻接点.如果有,则访问此顶点,进行前述类似的访问,如果没有,就在退回一步进行搜索,重复上述

差分约束小结

ZOJ 2770 Burn the Linked Camp /* ZOJ 2770 Burn the Linked Camp 差分约束 */ #include <iostream> #include <cstring> #include <cstdio> #include <queue> using namespace std; const int MAXN = 1009; struct Edge { int v, ne, c; } G[MAXN*MAXN]

数据降维方法小结

原文:http://blog.csdn.net/yujianmin1990/article/details/48223001 数据的形式是多种多样的,维度也是各不相同的,当实际问题中遇到很高的维度时,如何给他降到较低的维度上?前文提到进行属性选择,当然这是一种很好的方法,这里另外提供一种从高维特征空间向低纬特征空间映射的思路. 数据降维的目的 数据降维,直观地好处是维度降低了,便于计算和可视化,其更深层次的意义在于有效信息的提取综合及无用信息的摈弃. 数据降维的方法 主要的方法是线性映射和非线性

arcserver开发小结(三)

一.关于网络数据集的制作 由于要做实现网络分析的功能,而手中却没有网络数据集,关于网络数据集的制作,网上也有不少的资料.我参考的是ESRI为我们提供的帮助文档(Network_Analyst_Tutorial.pdf,该文档位于C:\Program Files\ArcGIS\Documentation,当然这个路径会随着ArcGIS安装路径的不同而有所不同),参照里面的做了下,我觉得最重要的是当你一步步NEXT后生成了.ND文件(网络数据集network dataset)之后,这里还没完,务必要

开发小结-流程管理类-下篇

改Bug和优化要不要同时进行 个人觉的,改Bug和优化,当优点的点和改Bug的点紧密相关联时时,改Bug和优化可以一同进行.而对于那些不怎么紧密的代码,优化可有可无时,那坚决不要优化.比方说,最开始进行释放内存,使用delete p; p = NULL;后来发现项目中已经有封装好宏,只需要一句话就可搞定.不过在使用该宏时,需要引入头文件.那么,这种情况下,就可以不进行优化,原来怎么写,现在就这么写.保持在同一个模块(.cpp)中,相关操作的一致性即可. 从冗余的实现到既可以满足业务功能,又保证每