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[10001],num;
long long dis[50008],vis[50008];
queue <long long> q;
const int inf=2147483647;
struct  Edge{
    int next,to,dis;
}edge[500008];
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=1;i<=n;i++)
     dis[i]=inf;//最开始先把每个点到起点的距离设为无限大
    dis[s]=0;//起点到起点的距离是0
    vis[s]=1;//将起点入队,用vis标记是否在队里
    q.push(s);
    while(!q.empty())
    {int u=q.front();
      q.pop();
      vis[u]=0;
      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]==0)
          {q.push(v);
            vis[v]=1;//标记
          }
        }
      }
    }
}
int main()
{
    scanf("%lld%lld%lld",&n,&m,&s);
    for(int i=1;i<=m;i++)
    {int f,t,d;
     scanf("%lld%lld%lld",&f,&t,&d);
     add(f,t,d);//存图
    }
    spfa();
    for(long long i=1;i<=n;i++)
     printf("%lld ",dis[i]);
}

 

转载于:https://www.cnblogs.com/lcez56jsy/p/10765099.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值