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求最短路径的更多相关文章

  1. SPFA求单源最短路径

    序 求最短路径的算法有很多,各有优劣. 比如Dijkstra(及其堆(STL-priority_queue)优化),但是无法处理负环的情况: 比如O(n^3)的Floyd算法:比如Bellman-Fo ...

  2. POJ 1860 Currency Exchange / ZOJ 1544 Currency Exchange (最短路径相关,spfa求环)

    POJ 1860 Currency Exchange / ZOJ 1544 Currency Exchange (最短路径相关,spfa求环) Description Several currency ...

  3. 《算法导论》读书笔记之图论算法—Dijkstra 算法求最短路径

    自从打ACM以来也算是用Dijkstra算法来求最短路径了好久,现在就写一篇博客来介绍一下这个算法吧 :) Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的 ...

  4. 求最短路径算法之SPAF算法。

    关于求最短路径: 求最短路径的算法有许多种,除了排序外,恐怕是OI界中解决同一类问题算法最多的了.最熟悉的无疑是Dijkstra(不能求又负权边的图),接着是Bellman-Ford,它们都可以求出由 ...

  5. SPFA算法——最短路径

    粗略讲讲SPFA算法的原理,SPFA算法是1994年西南交通大学段凡丁提出 是一种求单源最短路的算法 算法中需要用到的主要变量 int n;  //表示n个点,从1到n标号 int s,t;  //s ...

  6. 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 ...

  7. ACM - 最短路 - AcWing 851 spfa求最短路

    AcWing 851 spfa求最短路 题解 以此题为例介绍一下图论中的最短路算法 \(Bellman\)-\(Ford\) 算法.算法的步骤和正确性证明参考文章最短路径(Bellman-Ford算法 ...

  8. C++迪杰斯特拉算法求最短路径

    一:算法历史 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以 ...

  9. spfa求最长路

    http://poj.org/problem?id=1932 spfa求最长路,判断dist[n] > 0,需要注意的是有正环存在,如果有环存在,那么就要判断这个环上的某一点是否能够到达n点,如 ...

随机推荐

  1. full visualization vs part virtualization

    https://stackoverflow.com/questions/21462581/what-is-the-difference-between-full-para-and-hardware-a ...

  2. 博客 新址: https://pheromone.github.io/

    该博客暂时调整歇业,小店地址暂时搬迁至: https://pheromone.github.io/ 该博客只做旧文章的维护工作. 博客 新址:  https://pheromone.github.io ...

  3. ios jenkins从0快速配置

    1,安装:brew install jenkins2,命令行里:jenkins 回车,第一次会生成密码和保存密码的路径如:/Users/uname/.jenkins/secrets/initialAd ...

  4. ADO.NET读取配置文件

    App.config <?xml version="1.0" encoding="utf-8" ?> <configuration> & ...

  5. 【算法导论】【排序】—— 计数排序(counting sort)

    计数排序的特点: 需要额外的数组以存储: 中间过程数据(记为数组 C),数组 C 的下标是待排序序列的元素值,下标对应的值为出现的次数: 排序后的序列(记为 B),计数排序仅获取原始待排序序列的值,对 ...

  6. python库-Arrow处理时间

    Arrow是一个处理时间的python库,能一键转换dates/times/timestamps等时间格式而不需要大量导致各种时间模块和格式转换函数,十分快捷方便 使用Arrow需要两步转换操作: 1 ...

  7. Convolutional Neural Network Architectures for Matching Natural Language Sentences

    interaction  n. 互动;一起活动;合作;互相影响 capture vt.俘获;夺取;夺得;引起(注意.想像.兴趣)n.捕获;占领;捕获物;[计算机]捕捉 hence  adv. 从此;因 ...

  8. Python全站之路----常用模块----configparser模块

    config:配置    parser:解析 此模块用于生成和修改常见配置文档,当前模块的名称在 python 3.x 版本中变更为 configparser,在 python 2.x 里名字为 Co ...

  9. Java第2次作业

    我认为这一次的作业还是比较好的,对自己的学习有很大帮助.

  10. new和malloc

    1.申请的内存所在位置 自由存储区(free store)是C++基于new操作符的一个抽象概念,凡是new进行内存申请,该内存为自由存储区.堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于 ...