【算法】单元最短路径之Bellman-Ford算法和SPFA算法
SPFA是经过对列优化的bellman-Ford算法,因此,在学习SPFA算法之前,先学习下bellman-Ford算法。
bellman-Ford算法是一种通过松弛操作计算最短路的算法。
适用条件
1.单源最短路径(从源点s到其它所有顶点v);2.有向图&无向图(无向图可以看作(u,v),(v,u)同属于边集E的有向图);3.边权可正可负(如有负权回路输出错误提示);4.差分约束系统;
bellman-Ford的具体操作是这样的:
- 初始化,dis数组表示从起点到达第i个点的最短距离。初始化时:dis[i]=edge[起点][i];如果没有边相接,则设为MAXN;
- 循环n-1次,遍历每个边,将dis[边[i].目标节点]=min(dis[边[i].目标节点],dis[边[i].初始节点]+边[i].权值);
- 【可选】检验负权回路:判断边集合中的每一条边的两个端点是否收敛。如果存在未收敛的顶点,则算法返回false,表明问题无解;否则算法返回true,并且从源点可达的顶点v的最短距离保存在 dis[v]中。
#include <bits/stdc++.h>
using namespace std;
int n,m;
//Bellman-Ford algorithm
struct Edge
{
int a,b,v;
}edge[];
long long dis[];
void bellman_ford(int x)
{
dis[x]=;
for(int i=;i<=n-;i++)
{
for(int j=;j<=m;j++)
{
dis[edge[j].b]=min(dis[edge[j].b],dis[edge[j].a]+edge[j].v);
}
}
return ;
/*
bool flag = 1; //判断是否含有负权回路
for(int i = 1; i <= m; ++i) if(dis[edge[i].b] > dis[edge[i].a] + edge[i].cost)
{
flag = 0;
break;
}
return flag;
*/
}
int main()
{
int s;
cin>>n>>m>>s;
for(int i=;i<=m;i++)
{
scanf("%d%d%d",&edge[i].a,&edge[i].b,&edge[i].v);
}
for(int i=;i<=n;i++)dis[i]=;
bellman_ford(s);
for(int i=;i<=n;i++)
cout<<dis[i]<<" ";
return ;
}
这个算法在luogu上70分,TLE了两个测试点,因此需要学习一个更牛逼的算法,SPFA,听说这是一个交大的教授发明的。附上原论文连接:https://wenku.baidu.com/view/df249954d4d8d15abe234eff.html
SPFA算法的全称是:Shortest Path Faster Algorithm,是西南交通大学段凡丁于 1994 年发表的论文中的名字。不过,段凡丁的证明是错误的,且在 Bellman-Ford 算法提出后不久(1957 年 )已有队列优化内容,所以国际上不承认 SPFA 算法是段凡丁提出的。
为了避免最坏情况的出现,在正权图上应使用效率更高的Dijkstra算法。若给定的图存在负权边,类似Dijkstra算法等算法便没有了用武之地,SPFA算法便派上用场了。
#include <bits/stdc++.h>
using namespace std;
int n,m,start;
long long dis[],used[],head[];
int num_edge=;
struct Graph
{
int to,w,next;
}graph[];
bool spfa(int x)
{
queue <int> q;
dis[x]=;
used[x]=;
q.push(x);
while(!q.empty())
{
int u=q.front();
q.pop();
used[u]=;
for(int i=head[u];i;i=graph[i].next)
{
int v=graph[i].to;
long long Songchi=dis[u]+graph[i].w;
if(dis[v]>Songchi)
{
dis[v]=Songchi;
if(used[v]==)
{
used[v]=;
q.push(v);
}
}
}
}
return ;
}
void addedge(int from,int to,int dis)//邻接表存边
{
graph[++num_edge].next=head[from];
graph[num_edge].to=to;
graph[num_edge].w=dis;
head[from]=num_edge;
}
int main()
{
memset(head,,sizeof(head));
memset(used,,sizeof(used));
cin>>n>>m>>start;
for(int i=;i<=n;i++)dis[i]=;
for(int i=;i<=m;i++)
{
int a,b,w;
scanf("%d%d%d",&a,&b,&w);
addedge(a,b,w);
}
if(spfa(start))
{
for(int i=;i<=n;i++)
cout<<dis[i]<<" ";
}
}
【算法】单元最短路径之Bellman-Ford算法和SPFA算法的更多相关文章
- 0-1背包的动态规划算法,部分背包的贪心算法和DP算法------算法导论
一.问题描述 0-1背包问题,部分背包问题.分别实现0-1背包的DP算法,部分背包的贪心算法和DP算法. 二.算法原理 (1)0-1背包的DP算法 0-1背包问题:有n件物品和一个容量为W的背包.第i ...
- 【数据结构与算法】字符串匹配(Rabin-Karp 算法和KMP 算法)
Rabin-Karp 算法 概念 用于在 一个字符串 中查找 另外一个字符串 出现的位置. 与暴力法不同,基本原理就是比较字符串的 哈希码 ( HashCode ) , 快速的确定子字符串是否等于被查 ...
- 最短路径——Dijkstra算法和Floyd算法
Dijkstra算法概述 Dijkstra算法是由荷兰计算机科学家狄克斯特拉(Dijkstra)于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图(无 ...
- 最短路径Dijkstra算法和Floyd算法整理、
转载自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最短路径—Dijkstra算法和Floyd算法 Dijks ...
- 【转】最短路径——Dijkstra算法和Floyd算法
[转]最短路径--Dijkstra算法和Floyd算法 标签(空格分隔): 算法 本文是转载,原文在:最短路径-Dijkstra算法和Floyd算法 注意:以下代码 只是描述思路,没有测试过!! Di ...
- 最小生成树---Prim算法和Kruskal算法
Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...
- 最小生成树——Prim算法和Kruskal算法
洛谷P3366 最小生成树板子题 这篇博客介绍两个算法:Prim算法和Kruskal算法,两个算法各有优劣 一般来说当图比较稀疏的时候,Kruskal算法比较快 而当图很密集,Prim算法就大显身手了 ...
- prim 算法和 kruskal算法
Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...
- 词性标注算法之CLAWS算法和VOLSUNGA算法
背景知识 词性标注:将句子中兼类词的词性根据上下文唯一地确定下来. 一.基于规则的词性标注方法 1.原理 利用事先制定好的规则对具有多个词性的词进行消歧,最后保留一个正确的词性. 2.步骤 ①对词性歧 ...
随机推荐
- 支付宝小程序云开发(Serverless)
支付宝小程序云开发(Serverless) 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! 一.在支付宝账号里面开通小程序云服务 ...
- POJ2376Cleaning Shifts(区间覆盖贪心)
应该还是蛮简单的一题,但是因为模拟太差,一直没调出来....... \(显而易见的应该按照左区间从小到大排序,相等按照右区间大到小排序\). \(那么第一个区间的l一定要是1,而且必拿(否则没有区间能 ...
- 服务器3C直连网络好呢还是3C精品网络更好呢?
3C直连网络:通过用自有AS号与中国电信CTcc,中国联通CUcc,中国移动CMcc企业网进行直接接驳,提供对大陆方向有更高要求的网络接入服务. 简称:国内3c直连. 3C精品专线网:在3C直连基础上 ...
- Spring mvc的基本配置及工作原理
1.spring mvc框架搭建 需求:在浏览器输入一个请求login.do,跳转到登录成功界面. 第一步,创建web项目,导入jar包 注意: 第二步,在web.xml中配置spring的核心监听器 ...
- AXI总线slave模式下接收数据---verilog代码
AXI总线slave模式下接收数据---verilog代码 `timescale 1ns / 1ps ///////////////////////////////////////////////// ...
- equals方法和 == 的使用
equals方法的使用 equals方法 源码展示: public boolean equals(Object obj) { return (this == obj); } 解析: equals方法默 ...
- 24个经典的MySQL索引问题,你都遇到过哪些?
索引 1.什么是索引? 2.索引有哪些优缺点? 3.索引使用场景(重点) 4.索引有哪几种类型? 5.索引的数据结构(b树,hash) 6.索引的基本原理 7.索引算法有哪些? 8.索引设计的原则? ...
- Java Web项目部署到阿里云服务器(ECS)
本篇随笔只是记录博主第一次将自己的Java项目部署到阿里云服务器的大致过程,具体细节还请参考别的博文. 一.项目介绍 我做的项目是利用maven项目构建工具进行搭建基于SSM框架的代码共享管理系统,主 ...
- 数据结构----链表Link
链表简介与数据结构 单向链表也叫单链表,是表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域.这个链接指向链表中的下一个节点,而最后一个节点的链接域则指向一个空值. 单向链 ...
- Jenkins-插件开发(简单demo)
推荐:官网创建插件案例:https://jenkins.io/doc/developer/tutorial/run/ 官方的这篇文章讲的很详细了,我就补充补充其中遇到的一些问题. 前置条件:maven ...