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");
}
}

最新文章

  1. 将字符串转换成JSON对象
  2. mysql--测试前缀索引能否用于order by 或者 group by
  3. 2434: [Noi2011]阿狸的打字机 - BZOJ
  4. Linux 系统监控和诊断工具:lsof
  5. ie下面兼容性问题的一些总结
  6. ViewPager+Fragment的结合使用,实现QQ界面的理解
  7. Css3图片圆角,兼容所有浏览器
  8. Android中ExpandableListView控件基本使用
  9. PHP连接LDAP进行登录验证
  10. ABP框架系列之二十七:(Feature-Management-特征管理)
  11. 【翻译】WPF4.5新特性(MSDN的翻译读不太懂)
  12. CSS----学习
  13. thinkphp相关
  14. python list 使用技巧
  15. 【vue】父子组件间通信----传值
  16. PyQt5用QTimer编写电子时钟
  17. 重器--biomart
  18. 第十届蓝桥杯 试题 E: 迷宫
  19. KMP算法模板&amp;&amp;扩展
  20. 树形DP新识

热门文章

  1. wpf 依赖属性介绍
  2. 右键菜单添加包含ICON图片的快捷打开方式
  3. 关于charles抓不到js文件的问题
  4. css常用选择器选择器
  5. 百战程序员——EL、JSTL
  6. python的面试问题
  7. docker hub切换国内镜像
  8. 软件开发者路线图梗概&amp;书摘chapter5
  9. 关于pycharm中缩进、粘贴复制等文本编辑功能部分失效的解决办法
  10. 经典问题----拓扑排序(HDU2647)