单源最短路:SPFA算法细讲

SPFA算法是解决最短路问题的算法

今天来回顾一下单源最短路的问题:
利用SPFA算法可以高效的解决单源最短路问题,并且解决有无负环的问题


如该无向图所示:
假设我们的单源点是1
Part one:
我们先把1压入队列
队列q[1][][][][][][][]
然后进入while(!q.empty())
1出队,得到和1相连的点的最短距离
假设w代表边权

if(dis[2]>dis[1]+1-->2.w)
dis[2]=dis[1]+1-->2.w
if(!vis[2])//代表2没有在队列里
{
  vis[2]=1 //表示2即将入队
  q.push(2)//就将2入队
}//循环会进行三次,因为1连接了三个点
[2][7][6][][][]
并得到最初从单源点到2,7,6的距离
dis[2] dis[7] dis[6] 

Part two:
接下来每个点进行循环操作

while(!q.empty())//当无法更新时,队列会逐渐变空
{
   int x=q.front();
   q.pop();
   vis[x]=0 ;//该点出了队列,所以不在队列中
   for(int i=0;i<vec[x].size();i++)
   {
      int v=vec[x][i].to;
      int w=vec[x][i].w;
      if(dis[v]>dis[x]+w)
      {
         dis[v]=dis[x]+w;
         if(!vis[v])//判断该点是否在队列中如果不在,入队即可
         {vis[v]=1;
         q.push(v);
      }
   }
 }

板子代码:

#include<bits/stdc++.h>
using namespace std;
#define maxn 1005
struct node
{
    int v;//终点
    int w;//权值
}temp;
vector<node>vec[maxn];//建一个图
int n,m;//n个顶点,m条边
int dis[maxn];//代表从u--->s的距离
int vis[maxn];//做标记
void input()//输入
{
    int u,v,w;
    for(int i=0; i<m; i++)
    {
        scanf("%d %d %d",&u,&v,&w);
        temp.v=v;
        temp.w=w;
        vec[u].push_back(temp);//建双向边
        temp.v=u;
        vec[v].push_back(temp);
    }
}
void Spfa(int u)//单源点
{
    memset(dis,0x3f3f3f3f,sizeof(dis));//赋值为无穷
    memset(vis,0,sizeof(vis));//清空数组
    queue<int>q;
    q.push(u);//入队
    //vis[u]=0;
    dis[u]=0;
    while(!q.empty())//队列非空
    {
        int x=q.front();
        q.pop();
        vis[x]=0;
        for(int i=0; i<vec[x].size();i++)
        {
            int to=vec[x][i].v;
            printf("%d %d %d\n",x,to,vec[x][i].w);
            if(dis[to]>dis[x]+vec[x][i].w)
            {
                dis[to]=dis[x]+vec[x][i].w;
                if(!vis[to])
                {
                    vis[to]=1;
                    q.push(to);
                }
            }
        }

    }

}
int main()
{
scanf("%d %d",&n,&m);
input();
Spfa(1);
printf("%d\n",vec[1].size());
int v;
scanf("%d",&v);
printf("%d\n",dis[v]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值