spfa算法(java代码)

题目:

851. spfa求最短路 - AcWing题库

输入样例:

3 3

1 2 5

2 3 -3

1 3 4

输出样例:

 2

分析:

先去定义一个class 类似于c++里面的pair 里面有两个变量x, y 因为后面需要用优先队列来处理最短路问题需要指出比较x还是y 因此我们让这个pair类实现 Comparable 接口 实现里面的方法 去指出比较谁 按谁去比较

spfa的思路和dijkstra的代码基本上是一样的 但在st可逆不可以上进行了优化 spfa的st是可逆的,你只要出队列 就把你改为false 进来就改为true

SPFA算法不一样,它相当于采用了BFS,因此遍历到的结点都是与源点连通的,因此如果你要求的n和源点不连通,它不会得到更新,还是保持的0x3f3f3f3f

里面st boolean类型的数组的作用是:表明这个点在(true) 不在(false) 优先队列里面, 要是在的话 我就不加进去了 不在的话 我在把这个点加进去

代码:

import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;

/**
 * @Title: spfa
 * @Author FindYou
 * @description:
 */
public class spfa {
    public static int n, m;
    public static int[] h,  ne,  w, e, dis;
    public static boolean[] st;
    public static int idx;
    public static Queue<Pair> q = new PriorityQueue<>();

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        h = new int[m + 10];
        ne = new int[m + 10];
        w = new int[m + 10];
        e = new int[m + 10];
        dis = new int[m + 10];
        st = new boolean[n + 10];
        init(); // 初始化 要记得
        
        for(int i = 1; i <= m; ++ i ) {
            int a, b, c;
            a = sc.nextInt();
            b = sc.nextInt();
            c = sc.nextInt();
            add(a, b, c);
        }
        spfa();
        if(dis[n] == 0x3f3f3f3f) {
            System.out.println("impossible");
        } else {
            System.out.println(dis[n]);
        }
    }

    public static void add(int a, int b, int c) {

        e[idx] = b; // 当前这个点是 b
        w[idx] = c; // 这个的权值是c
        ne[idx] = h[a];
        h[a] = idx ++ ;
    }

    public static void init() {
        idx = 0;
        for(int i = 1; i <= n; ++ i ) {
            h[i] = -1;
            dis[i] = 0x3f3f3f3f;
        }
        dis[1] = 0;
    }

    public static void spfa() {
        q.add(new Pair(0, 1)); // 0是距离 1是点了
        st[1] = true;
        while (q.size() != 0 ) {
            Pair t = q.poll();
            int pos = t.y; // 吧这个点给取出来了
            st[pos] = false; // 那么就标记为false
            for(int i = h[pos]; i != -1; i = ne[i]) {
                int j = e[i];
                if(dis[j] > dis[pos] + w[i]) {
                    dis[j] = dis[pos] + w[i];
                    if(!st[j]) {
                        st[j] = true;
                        q.add(new Pair(dis[j], j));
                    }
                }
            }
        }
    }
}

class Pair implements Comparable<Pair>{
    int x;
    int y;
    public  Pair(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public Pair() {
    }

    @Override
    public int compareTo(Pair o) {
        if(this.x != o.x) {
            return this.x - o.x;
        } else {
            return this.y - o.y;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FindYou.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值