AcWing 851. spfa求最短路(SPFA算法)

本文深入解析了SPFA算法,一种优化的Bellman-Ford算法,用于解决带负权边的有向图中单源最短路径问题。文章通过具体实例展示了算法的实现过程,包括数据结构的设计和代码实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

给定一个n个点m条边的有向图,图中可能存在重边和自环, 边权可能为负数

请你求出1号点到n号点的最短距离,如果无法从1号点走到n号点,则输出impossible。

数据保证不存在负权回路。

输入格式

第一行包含整数n和m。

接下来m行每行包含三个整数x,y,z,表示存在一条从点x到点y的有向边,边长为z。

输出格式

输出一个整数,表示1号点到n号点的最短距离。

如果路径不存在,则输出”impossible”。

数据范围

1≤n,m≤1051≤n,m≤105,
图中涉及边长绝对值均不超过10000。

输入样例:

3 3
1 2 5
2 3 -3
1 3 4

输出样例:

2

SPFA思想:

优化BellmanFord算法:当距离更新的时候(也就是它的距离变小了,它变小了,自然后面变小的几率更大),把它插进队列去更新。



import java.io.*;
import java.lang.*;
import java.util.*;

class Main{
    
    static int n = 0, m = 0, N = 100010;
    static int[] h = new int[N], w = new int[N], e = new int[N], ne = new int[N];
    static int idx = 1;
    static Deque<Integer> q = new ArrayDeque<>();
    static int[] dist = new int[N];
    static boolean[] f = new boolean[N];
    static int spfa(){
        Arrays.fill(dist, 0x3f3f3f3f);
        dist[1] = 0;
        f[1] = true;
        q.offer(1);
        while(q.size() != 0){
            int a = q.poll();
            f[a] = false;
            for(int i = h[a]; i != -1; i = ne[i]){
                int j = e[i];
                if(dist[j] > dist[a] + w[i]){//遇到小的就更新
                    dist[j] = dist[a] + w[i];//更新距离
                    if(!f[j]){//如果之前没插入则插入,差如果就不插入了
                        q.offer(j);
                        f[j] = true;
                    }
                }
            }
        }
        if(dist[n] == 0x3f3f3f3f)return -1;
        return dist[n];
    }
    
    static void add(int a, int b, int wc){
        e[idx] = b; w[idx] = wc; ne[idx] = h[a]; h[a] = idx++;
    }
    public static void main(String[] args)throws Exception{
        BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
        String[] params = buf.readLine().split(" ");
        n = Integer.valueOf(params[0]);
        m = Integer.valueOf(params[1]);
        Arrays.fill(h, -1);
        for(int i = 1; i <= m; ++i){
            String[] info = buf.readLine().split(" ");
            int a = Integer.valueOf(info[0]);
            int b = Integer.valueOf(info[1]);
            int wc = Integer.valueOf(info[2]);
            add(a, b, wc);
        }
        int res = spfa();
        if(res == -1){
            System.out.print("impossible");
        }else
            System.out.print(res);
    }
}

自己定义队列版本

import java.io.*;
import java.lang.*;
import java.util.*;


class Main{
    
    static int n = 0, m = 0, N = 100010, INF = 0x3f3f3f3f;
    static int[] qu = new int[N];//队列
    static int[] h = new int[N];
    static int[] e = new int[N], ne = new int[N], w = new int[N];
    static int idx = 1;
    static int[] dist = new int[N];
    
    
    static int spfa(){
        Arrays.fill(dist, INF);
        int hh = 0, tt = -1;
        dist[1] = 0;
        qu[++tt] = 1;
        while(hh <= tt){
            int a = qu[hh++];
            for(int i = h[a]; i != -1; i = ne[i]){
                int j = e[i];
                if(dist[j] > dist[a] + w[i]){
                    dist[j] = dist[a] + w[i];
                    qu[++tt] = j;
                }
            }
        }
        if(dist[n] < INF /2)return dist[n];
        return -1;
    }
    
    
    static void add(int a, int b, int wt){
        e[idx] = b; w[idx] = wt; ne[idx] = h[a]; h[a] = idx++;
    }
    
    public static void main(String[] args)throws Exception{
        BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
        String[] params = buf.readLine().split(" ");
        n = Integer.valueOf(params[0]);
        m = Integer.valueOf(params[1]);
        Arrays.fill(h, -1);
        for(int i = 1; i <= m; ++i){
            String[] info = buf.readLine().split(" ");
            int a = Integer.valueOf(info[0]);
            int b = Integer.valueOf(info[1]);
            int wi = Integer.valueOf(info[2]);
            add(a, b, wi);
        }
        int res = spfa();
        System.out.print(res == -1 ? "impossible" : res);
    }
}

优化版:

import java.io.*;
import java.lang.*;
import java.util.*;


class Main{
    
    static int n = 0, m = 0, N = 100010, INF = 0x3f3f3f3f;
    static int[] qu = new int[N];//队列
    static int[] h = new int[N];
    static int[] e = new int[N], ne = new int[N], w = new int[N];
    static int idx = 1;
    static int[] dist = new int[N];
    static boolean[] f = new boolean[N];
    
    static int spfa(){
        Arrays.fill(dist, INF);
        int hh = 0, tt = -1;
        dist[1] = 0;
        f[1] = true;
        qu[++tt] = 1;
        while(hh <= tt){
            int a = qu[hh++];
            f[a] = false;
            for(int i = h[a]; i != -1; i = ne[i]){
                int j = e[i];
                if(dist[j] > dist[a] + w[i]){
                    dist[j] = dist[a] + w[i];
                    if(f[j])continue;
                    qu[++tt] = j;
                    f[j] = true;
                }
            }
        }
        if(dist[n] < INF /2)return dist[n];
        return -1;
    }
    
    
    static void add(int a, int b, int wt){
        e[idx] = b; w[idx] = wt; ne[idx] = h[a]; h[a] = idx++;
    }
    
    public static void main(String[] args)throws Exception{
        BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
        String[] params = buf.readLine().split(" ");
        n = Integer.valueOf(params[0]);
        m = Integer.valueOf(params[1]);
        Arrays.fill(h, -1);
        for(int i = 1; i <= m; ++i){
            String[] info = buf.readLine().split(" ");
            int a = Integer.valueOf(info[0]);
            int b = Integer.valueOf(info[1]);
            int wi = Integer.valueOf(info[2]);
            add(a, b, wi);
        }
        int res = spfa();
        System.out.print(res == -1 ? "impossible" : res);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值