Spfa求最短路径
spfa求最短路径,其思想就是遍历每一个点,将没有入队的点入队,从这个点开始不断修改能够修改的最小路径,直到队空。不过这里一个点可以重复入队。
这个需要有存图的基础--------->前向星存图
举个栗子

这里有一张图,边旁边的数字为这条边的权值。旁边的图为边的编号
用dis[i]来记录起点到i的最小路径长度(一开始都是inf)
求最小路径,首先从起点开始,遍历起点的每一条出边,并将要修改dis[i]的出边终点(没有入队的点)入队,再不断出队,对每个队中的点进行相同的操作。
模拟一下。
首先将①入队。dis[1]=0。①的第一条出边的终点是②,将②入队,同时修改dis[2]=3.
下一条出边是第四条边,终点为③,将③入队,修改dis[3]=4.
将④入队,dis[4]=6。
进行完这一步,①出队,同时将①标记为未入队,对②进行操作。
②的第一条出边的终点为①,不修改,不入队。
next:终点为③,9+3>4,不修改 ,不入队。
next:将⑥入队,dis[6]=10+3=13
如此不断更新~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
来我们看一下代码
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#define spfa zhx_akioi
using namespace std;
long long n,m,s,head[],num;
long long dis[],vis[];
queue <long long> q;
const int inf=;
struct Edge{
int next,to,dis;
}edge[];
void add(int f,int t,int d)
{ num++;
edge[num].next=head[f];
edge[num].to=t;
edge[num].dis=d;
head[f]=num;
}
void spfa()
{ for(int i=;i<=n;i++)
dis[i]=inf;//最开始先把每个点到起点的距离设为无限大
dis[s]=;//起点到起点的距离是0
vis[s]=;//将起点入队,用vis标记是否在队里
q.push(s);
while(!q.empty())
{int u=q.front();
q.pop();
vis[u]=;
for(int i=head[u];i;i=edge[i].next)//从出队的点开始,遍历这个点的每条出边
{ int v=edge[i].to;
if(dis[v]>dis[u]+edge[i].dis)//如果这个点当前到起点的距离大于出队的点到起点的距离加上当前边的距离,即可以更新,就更新,并将更新的点入队
{ dis[v]=dis[u]+edge[i].dis;
if(vis[v]==)
{q.push(v);
vis[v]=;//标记
}
}
}
}
}
int main()
{
scanf("%lld%lld%lld",&n,&m,&s);
for(int i=;i<=m;i++)
{int f,t,d;
scanf("%lld%lld%lld",&f,&t,&d);
add(f,t,d);//存图
}
spfa();
for(long long i=;i<=n;i++)
printf("%lld ",dis[i]);
}
判负环
如果图里面没有负环,那么一个点最多入队n次。如果有点入队次数大于n次就说明有负环。
当然还可以把spfa改成dfs版,即一直沿着某条路进行更新,如果再一次松弛到了该路径上松弛过的点,就证明有负环(可能会TLE)
bfs版:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#define pa pair<int,int>
#include<ctime>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=;
inline ll read()
{
char ch=getchar();
ll x=;
bool f=;
while(ch<''||ch>'')
{
if(ch=='-') f=;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=(x<<)+(x<<)+(ch^);
ch=getchar();
}
return f?-x:x;
}
int t,n,m,head[],cnt,dis[],vis[],in[];
struct E{
int to,nxt,dis;
}ed[];
void init()
{
cnt=;
memset(head,,sizeof(head));
memset(in,,sizeof(in));
memset(dis,0x3f,sizeof(dis));
memset(vis,,sizeof(vis));
}
void add(int fr,int to,int dis)
{
ed[++cnt].to=to;
ed[cnt].dis=dis;
ed[cnt].nxt=head[fr];
head[fr]=cnt;
}
bool spfa()
{
queue <int> q;
dis[]=;
vis[]=;
in[]++;//in统计入队次数
q.push();
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=;
for(int e=head[u];e;e=ed[e].nxt)
{
int v=ed[e].to;
if(dis[v]>dis[u]+ed[e].dis)
{
dis[v]=dis[u]+ed[e].dis;
if(!vis[v])
{
vis[v]=;
in[v]++;
if(in[v]>n) return ;
q.push(v);
}
}
}
}
return ;
}
int main()
{
t=read();
while(t--)
{
init();
n=read();m=read();
for(int i=;i<=m;i++)
{
int fr=read(),to=read(),dis=read();
add(fr,to,dis);
if(dis>=)
add(to,fr,dis);
}
if(spfa()) printf("YE5\n");//模板题让你输出的奇奇怪怪的东西
else printf("N0\n");
}
}
dfs版:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#define pa pair<int,int>
#include<ctime>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=;
inline ll read()
{
char ch=getchar();
ll x=;
bool f=;
while(ch<''||ch>'')
{
if(ch=='-') f=;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=(x<<)+(x<<)+(ch^);
ch=getchar();
}
return f?-x:x;
}
int t,n,m,head[],cnt,dis[],vis[],in[];
int sta[],top;
bool fh;
struct E{
int to,nxt,dis;
}ed[];
void init()
{
cnt=;top=;fh=;
memset(head,,sizeof(head));
memset(in,,sizeof(in));
memset(dis,0x3f,sizeof(dis));
memset(vis,,sizeof(vis));
}
void add(int fr,int to,int dis)
{
ed[++cnt].to=to;
ed[cnt].dis=dis;
ed[cnt].nxt=head[fr];
head[fr]=cnt;
}
void spfa(int u)
{
if(fh) return ;
vis[u]=;
for(int e=head[u];e;e=ed[e].nxt)
{
if(fh) return ;
int v=ed[e].to;
if(dis[v]>dis[u]+ed[e].dis)
{
dis[v]=dis[u]+ed[e].dis;
if(vis[v])
{
fh=;
return;
}
spfa(v);
}
}
vis[u]=;
}
int main()
{
t=read();
while(t--)
{
init();
n=read();m=read();
for(int i=;i<=m;i++)
{
int fr=read(),to=read(),dis=read();
add(fr,to,dis);
if(dis>=)
add(to,fr,dis);
}
dis[]=;
spfa();
if(fh) printf("YE5\n");
else printf("N0\n");
}
}
Spfa求最短路径的更多相关文章
- SPFA求单源最短路径
序 求最短路径的算法有很多,各有优劣. 比如Dijkstra(及其堆(STL-priority_queue)优化),但是无法处理负环的情况: 比如O(n^3)的Floyd算法:比如Bellman-Fo ...
- POJ 1860 Currency Exchange / ZOJ 1544 Currency Exchange (最短路径相关,spfa求环)
POJ 1860 Currency Exchange / ZOJ 1544 Currency Exchange (最短路径相关,spfa求环) Description Several currency ...
- 《算法导论》读书笔记之图论算法—Dijkstra 算法求最短路径
自从打ACM以来也算是用Dijkstra算法来求最短路径了好久,现在就写一篇博客来介绍一下这个算法吧 :) Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的 ...
- 求最短路径算法之SPAF算法。
关于求最短路径: 求最短路径的算法有许多种,除了排序外,恐怕是OI界中解决同一类问题算法最多的了.最熟悉的无疑是Dijkstra(不能求又负权边的图),接着是Bellman-Ford,它们都可以求出由 ...
- SPFA算法——最短路径
粗略讲讲SPFA算法的原理,SPFA算法是1994年西南交通大学段凡丁提出 是一种求单源最短路的算法 算法中需要用到的主要变量 int n; //表示n个点,从1到n标号 int s,t; //s ...
- POJ 2387 Til the Cows Come Home Dijkstra求最短路径
Til the Cows Come Home Bessie is out in the field and wants to get back to the barn to get as much s ...
- ACM - 最短路 - AcWing 851 spfa求最短路
AcWing 851 spfa求最短路 题解 以此题为例介绍一下图论中的最短路算法 \(Bellman\)-\(Ford\) 算法.算法的步骤和正确性证明参考文章最短路径(Bellman-Ford算法 ...
- C++迪杰斯特拉算法求最短路径
一:算法历史 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以 ...
- spfa求最长路
http://poj.org/problem?id=1932 spfa求最长路,判断dist[n] > 0,需要注意的是有正环存在,如果有环存在,那么就要判断这个环上的某一点是否能够到达n点,如 ...
随机推荐
- 在执行hadoop fs命令时,出现WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable错误
错误呈现: 解决过程: (参考链接:https://www.cnblogs.com/kevinq/p/5103653.html) 1.输出hadoop的详细日志,并执行hadoop fs命令来查看错误 ...
- 1--Test NG--常见测试和注解
第一:注解 (1)@test (2)@BeforeMethod,@AfterMethod (3)@BeforeClass,@AfterClass (4)@BeforeSuite,@AfterSuite ...
- CSS盒子内容
内边距 内边距(padding):内容与边框之间的距离 注意:padding 只能移动盒子的内容 padding属性联写: padding: 10px: 内边距的上下左右都移动 padding: 10 ...
- read读文件
FILE *fp=fopen("F:\\QQBrowser_Setup_DNF.exe", "rb"); fseek(fp, , SEEK_END); long ...
- NSArray NSMutableArray
NSArray 或者 NSMUtableArray 去除重复的数据: 原来集合操作可以通过valueForKeyPath来实现的,去重可以一行代码实现: [array valueForKeyPath: ...
- kettle之linux使用kettle
Kettle可以在Window.Linux.Unix上运行,数据抽取高效稳定,使用之前需要准备环境. 准备java环境,这里就不赘述了,建议jdk7以上版本. 上传kettle压缩包,并解压,我解压的 ...
- JavaSE-2018.12.20更新
JDK:Java Development Kit(java开发工具包,是提供给java开发人员使用的,包含了开发工具(编译工具javac.exe和打包工具jar.exe等)+JRE) JRE:Java ...
- js数组操作-最佳图解
js数组操作-最佳图解
- linux解压缩文件名乱码问题 亲测可用
unar 这个工具会自动检测文件的编码,也可以通过-e来指定:unar file.zip 即可解压出中文文件.
- 微信小程序之跳转、请求、带参数请求小例子
wx.request(OBJECT) wx.request发起的是 HTTPS 请求.一个微信小程序,同时只能有5个网络请求连接. 具体参数说明参看微信小程序官方文档-发起请求. 例: //当页面加载 ...