spfa算法

  1. spfa算法简介
    spfa算法是shortest path fastest algorithm的缩写。再通常情况下,是一种比较高效的求解最短路的算法。spfa的本质是广度优先搜索,将图所有的边都遍历一遍。平均时间复杂度是O(m),最坏时间复杂度是O(mn),其中m是图的边数。

  2. spfa算法的用途
    spfa算法用来解决单源最短路问题,可以求解从某个点开始,到图中其他所有点的最短距离。

  3. spfa算法的实现步骤

    1. 实现spfa算法需要一个队列q,一个标记数组vis[N]用来标记某点是否在队列中。数组dist[N],用来存储起点到某个点的最短距离。
    2. 初始化dist数组为正无穷
    3. 从起点开始枚举每个点的所有子节点,设父节点到子节点的距离为s,父节点到起点的距离为dist[u],子节点到起点的距离为dist[v],如果
      dist[u]+s<dist[v]
      当且仅当上式成立时就更新dist[v],如果v没有在队列中,就将v入队。
  4. 一个示例图:

图中红色标号是每条边的搜索顺序。

  1. 一道例题
    acwing 1129. 热浪
    德克萨斯纯朴的民众们这个夏天正在遭受巨大的热浪!!!

他们的德克萨斯长角牛吃起来不错,可是它们并不是很擅长生产富含奶油的乳制品。

农夫John此时身先士卒地承担起向德克萨斯运送大量的营养冰凉的牛奶的重任,以减轻德克萨斯人忍受酷暑的痛苦。

John已经研究过可以把牛奶从威斯康星运送到德克萨斯州的路线。

这些路线包括起始点和终点一共有 T 个城镇,为了方便标号为 1 到 T。

除了起点和终点外的每个城镇都由 双向道路 连向至少两个其它的城镇。

每条道路有一个通过费用(包括油费,过路费等等)。

给定一个地图,包含 C 条直接连接 2 个城镇的道路。

每条道路由道路的起点 Rs,终点 Re 和花费 Ci 组成。

求从起始的城镇 Ts 到终点的城镇 Te 最小的总费用。

输入格式
第一行: 4 个由空格隔开的整数: T,C,Ts,Te;

第 2 到第 C+1 行: 第 i+1 行描述第 i 条道路,包含 3 个由空格隔开的整数: Rs,Re,Ci。

输出格式
一个单独的整数表示从 Ts 到 Te 的最小总费用。

数据保证至少存在一条道路。

数据范围
1≤T≤2500,
1≤C≤6200,
1≤Ts,Te,Rs,Re≤T,
1≤Ci≤1000
输入样例:
7 11 5 4
2 4 2
1 4 3
7 2 2
3 4 3
5 7 5
7 3 3
6 1 1
6 3 4
2 4 3
5 6 3
7 2 1
输出样例:
7
代码:

#include<bits/stdc++.h>
using namespace std;
#define N 2510
#define M 16300
int w[M],to[M],ne[M],h[N];
int cnt;
int dist[N],vis[N];
int n,m,be,en;
queue<int>q;
void add( int a,int b,int c){
    w[cnt]=c;to[cnt]=b;ne[cnt]=h[a];h[a]=cnt++;
}
void spfa(){
    q.push(be);
    while(!q.empty()){
        int now=q.front();
        vis[now]=0;//出队之后将标记置为0
        q.pop();
        for( int i=h[now];i!=-1;i=ne[i]){
            int j=to[i];
            // dist[j]=min(dist[j],dist[now]+w[i]);
            if(dist[j]>dist[now]+w[i]){
                dist[j]=dist[now]+w[i];
               //j点的最大值得到了更新,如果j不在队中,需要将j重新入队
                if(vis[j]==0){
                    vis[j]=1;
                    q.push(j);
                }
            }
        }
    }
}
int main(){
    cin>>n>>m>>be>>en;
    memset(h,-1,sizeof(h));
    memset(dist,0x3f,sizeof(dist));
    for( int i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
        add(b,a,c);
    }
    dist[be]=0;
    vis[be]=1;
    spfa();
    cout<<dist[en];
}
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值