一:dijkstra算法
时间复杂度,用优先级队列优化的话,O((M+N)logN)
求单源最短路径,要求所有边的权值非负。若图中出现权值为负的边,Dijkstra算法就会失效,求出的最短路径就可能是错的。

设road[i][j]表示相邻的i到j的路长
U集合存储已经求得的到源点最短路径的节点,S集合表示还没求得的节点
dis[i]表示i到源节点(设为0)的最短路径
vis[i]=1表示i节点在U集合中

刚开始dis[0]=0,vis[0]=1;dis[i]=maxn,vis[i]=0;
for 1 to N:
1:从S集合中找出dis[]最小的节点i
将i从S中移出,插入到U中,即vis[i]=1;
2:遍历所有与i相邻的节点j
若dis[i]+road[i][j]<dis[j]
则dis[j]=dis[i]+road[i][j];
3:转1

//求其它点到源点s的最短路径,用优先级队列优化

int road[maxn][maxn];//road[i][j]表示i与j的距离(这里指进过该条路的时间)
int dis[maxn];//dis[i]表示i点到源点s的最短路径大小
int vis[maxn];//vis[i]=1表示节点i已经求过到源点的单源最短路径
vector<int> link[maxn];//link[i]表示i与哪些点连接
int n,m; struct Node{
int u,dis; //u:节点 dis:到源点s的距离 bool operator<(const Node tmp) const{
return dis>tmp.dis; //优先级序列默认的是最先取出的是“最大的”。所以这里要从大到小排序
}
}; void dijkstra() {
priority_queue<Node> q;
Node tmp,a;
for(int i=;i<maxn;i++)
dis[i]=INF;
memset(vis,,sizeof(vis));
dis[s]=;
a.dis=;
a.u=s;
q.push(a);
while(!q.empty()) {
tmp=q.top();
q.pop();
int idx=tmp.u;
vis[idx]=;
for(int k=; k<link[idx].size(); k++) {
int v=link[idx][k];
if(!vis[v]) {
if(dis[idx]+road[idx][v]<dis[v]) {
dis[v]=dis[idx]+road[idx][v];
a.dis=dis[v];
a.u=v;
q.push(a);
}
}
}
}
}

二:Bellman-Ford 算法
邻接矩阵:O(V^3) 邻接表:O(VE)
Bellman-Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题。
如果存在负权回路,算法会返回false值,表明最短路不存在。(负权回路的含义是,回路的权值和为负)

BF算法为什么要进行n-1次迭代?这是由于“两点间如果有最短路,那么每个节点最多经过一次。也就是说,这条路不超过n-1条边”。
因为如果一个节点经过了两次,那么我们走了一个圈。若这个圈的权为正,显然不划算;若是负圈,那么最短路不存在;若是零圈,去掉不影响最优值。

很多时候,得到最优值需要的迭代次数远小于V-1。因此在迭代过程中,可以加个判断,要是发现所有节点的最短路径估计值没有更新,就可以退出了。

//求源点s到各节点的最短路
bool Bellman_Ford(int s){
//初始化
for(int i=;i<n;i++){
dist[i]=INF; //i到源点s的距离
pre[i]=-; //i的前驱节点,用于输出路径
}
dist[s]=;
for(int i=;i<n;i++){ //进行n-1次迭代
for(each(u,v)∈E){ //对所有边松弛一次
if(dist[u]+w[u][v]<dist[v]){
dist[v]=dist[u]+w[u][v];
pre[v]=u;
}
}
}
//若进行n-1次迭代后,仍然存在可以更新的路径,表明有负权回路,返回false
for(each(u,v)∈E){
if(dist[u]+w[u][v]<dist[v]){
return false;
}
}
return true;
}

三:SPFA(Shortest Path Faster Algorithm)

时间复杂度:O(kE),k一般小于等于2。但SPFA算法不稳定,即对于某些特殊的数据,k可能比较大。

是在BF的基础上,采用队列进行优化,算法大致流程是用一个队列来进行维护。 初始时将源加入队列,

每次从队列中取出一个元素,并对所有与他相邻的点进行松弛,若某个相邻的点松弛成功,则将其入队。 直到队列为空时算法结束。

存在负权回路的话,就需要创建一个COUNT数组,当某点的入队次数超过V(顶点数)返回。

int vis[i]://用来标记点i是否在队列中
//计算源点s至各节点的最短路长,这里遍历采用邻接链表——链式前向星
void SPFA(int s){
queue<int> q;
int u,v;
dist[s]=;
q.push(s);
vis[s]=;
while(!q.empty()){
u=q.front();
q.pop();
vis[u]=;
//对u的所有出边的端点进行松弛操作,如果可以经过u使得源点到v的路径变短,则更新
for(int k=head[u];k!=-;k=edge[k].next){
v=edge[k].to;
if(dist[u]+w[u][v]<dist[v]){
dist[v]=dist[u]+w[u][v];
//若点v不在队列里,则加入到队列中
if(!vis[v]){
q.push(v);
vis[v]=;
}
}
}
}
}

下面给出链式前向星的模板:

//邻接链表存储——链式前向星
//head[i]:表示父亲节点i的所有指向子节点的最后一次与i连接的边的序号
//edge[k].next:表示编号为k的边的相邻的一条边的编号,这两条边是同一节点引出的
//edge[k].to:表示编号为k的边所指向的节点编号
//int head[n],tot;
//n为顶点数,m为边数 struct edge
{
int next,to;
}edge[m] void add(int x,int y)
{
edge[tot].next =head[x];
edge[tot].to = y;
head[x] = tot++;
}
//初始化
void init()
{
memset(head,-,sizeof(head))
tot = ;
} //遍历与x相邻的所有点v
for(int k = head[x];k!=-;k=edge[k].next)
{
int v = edge[k].to;
//...
}

单元最短路径算法模板汇总(Dijkstra, BF,SPFA),附链式前向星模板的更多相关文章

  1. 洛谷 P4779 【dijkstra】+(堆优化)+(链式前向星) (模板题)

    <题目链接> 题目描述 给定一个 N 个点, M 条有向边的带非负权图,请你计算从 S 出发,到每个点的距离. 数据保证你能从 S 出发到任意点. 输入格式: 第一行为三个正整数 N,M, ...

  2. spfa+链式前向星模板

    #include<bits/stdc++.h> #define inf 1<<30 using namespace std; struct Edge{ int nex,to,w ...

  3. POJ - 1330 Nearest Common Ancestors 最近公共祖先+链式前向星 模板题

    A rooted tree is a well-known data structure in computer science and engineering. An example is show ...

  4. 【模板】链式前向星+spfa

    洛谷传送门--分糖果 博客--链式前向星 团队中一道题,数据很大,只能用链式前向星存储,spfa求单源最短路. 可做模板. #include <cstdio> #include <q ...

  5. 洛谷P3371单源最短路径Dijkstra版(链式前向星处理)

    首先讲解一下链式前向星是什么.简单的来说就是用一个数组(用结构体来表示多个量)来存一张图,每一条边的出结点的编号都指向这条边同一出结点的另一个编号(怎么这么的绕) 如下面的程序就是存链式前向星.(不用 ...

  6. 模板 Dijkstra+链式前向星+堆优化(非原创)

    我们首先来看一下什么是前向星.   前向星是一种特殊的边集数组,我们把边集数组中的每一条边按照起点从小到大排序,如果起点相同就按照终点从小到大排序, 并记录下以某个点为起点的所有边在数组中的起始位置和 ...

  7. 最短路 spfa 算法 && 链式前向星存图

    推荐博客  https://i.cnblogs.com/EditPosts.aspx?opt=1 http://blog.csdn.net/mcdonnell_douglas/article/deta ...

  8. 【最短路】Dijkstra+ 链式前向星+ 堆优化(优先队列)

    Dijkstra+ 链式前向星+ 优先队列   Dijkstra算法 Dijkstra最短路算法,个人理解其本质就是一种广度优先搜索.先将所有点的最短距离Dis[ ]都刷新成∞(涂成黑色),然后从起点 ...

  9. SPFA + 链式前向星(详解)

    求最短路是图论中最基础的算法,最短路算法挺多,本文介绍SPFA算法. 关于其他最短路算法,请看我另一篇博客最短路算法详解 链式前向星概念 简单的说,就是存储图的一个数据结构.它是按照边来存图,而邻接矩 ...

随机推荐

  1. [.NET] 打造防“狼”神器 :任务栏篇

    @微微一笑:本文标题纯属自娱自乐. 隐藏任务栏效果图: 对比 说起来惭愧,上面这个隐藏任务栏功能,只是完成了我一半的预想.本想是可以选择性的隐藏任务栏上的某个TaskBarButton,但是Win7+ ...

  2. Oracle Study Note : Tablespace and Data Files

    1.how to create a tablespace that employs the most common features create tablespace tb_name #create ...

  3. OC编写使用调试器

    OC编写使用调试器 编写代码免不了,Bug.那么Debug就是程序员的必备技能了.本文和大家一起探讨,如何在应用开发编写代码过程中,使用日志项消息:以及使用动作.条件.迭代控制增强断点. 记录信息 在 ...

  4. 关于Haproxy安装和配置:负载配置【haproxy.cfg】问题记录

    1.  存放地址: more /etc/haproxy/haproxy.cfg ps -ef | grep haproxy 看看有没有haproxy的进程就是了 或者看看服务器的23306的端口有没有 ...

  5. 怎么解决/bin/sh: arm-linux-gcc: not found make

      1.arm-linux-gcc 环境变量没有设,所以找不到这个编译器 在/etc/profile里添加arm-linux-gcc的存放路径 sudo -s gedit /etc/profile 编 ...

  6. Xcode真机调试错误之"Please valify your...clock not set"

    乍一看错误信息是证书过期,其实是描述证书错乱了. Xcode->Preferences->Account  将选中其中一个描述文件 show in finder,将里面的全都删除.

  7. App_Store - IOS应用审核的时隐私政策模板

    隐私政策  Poposoft尊重并保护所有使用服务用户的个人隐私权.为了给您提供更准确.更有个性化的服务,Poposoft会按照本隐私权政策的规定使用和披露您的个人信息.但Poposoft将以高度的勤 ...

  8. extjs实现多国语音切换

    http://kuyur.info/blog/archives/2490 http://blog.chinaunix.net/uid-28661623-id-3779637.html http://b ...

  9. Window7上搭建symfony开发环境(PEAR)

    http://blog.csdn.net/kunshan_shenbin/article/details/7162243 1. 更新PEAR 进入PHP所在目录,找到go-pear.bat并双击. 一 ...

  10. scjp考试准备 - 2 - 逻辑运算及类型转换

    判断如下代码的执行结果: public class Spock{ public static void main(String[] args){ Long tail = 2000L; Long dis ...