图论记录之Bellman-Ford 算法

算法思想

java 复制代码
迭代n次 即循环n次
	遍历所有边,对于每一条边(a,b,v)表示a->b的权值为v
	若从起点到b的距离大于从起点到a的距离+a到b的距离就更新
	这里代码中的体现在于dist[b] = min(dist[b],dist[a]+v])
	没了

循环n次,对于所有的边一定满足
dist[b] <= dist[a]+w,这东西叫做三角不等式,更新一次叫做松弛操作看弹幕的时候看到了一个差分约束系统挺高大上的

适用情况

适用于有负权边的最短路问题,但对于负权回路没有办法,但可以判定有没有负权回路

边数限制也可以用,注意若有边数限制,需要加上一个备份数组,防止发生串联更新,关于这个串联更新的意思就是说,a点被更新了,拿着更新后的a点去更新其他点,而其他点需要的是更新前的a点的值,

负权回路与最短路径的存在性的相关性问题

只要负权回路不在最短路径上,那么就存在最短路径

比如1->2 2是终点,存在负权回路,但是也存在最短路径

判定有没有负权回路

它可以判定,但是一般不用这个算法,用SPFA,因为时间复杂度大

迭代了k次,k的含义从1号点经过不少于k条边走到每个点的最短路的距离,若第n迭代的时候又更新了某条边的话,存在一条边数是大于等于n的最短路径,那么就可以判定是有负权回路,

我的理解就是 n个点的最短路径只有n-1条边,若大于等于了n可以判定有环,而且还是更新后的(也就是说当前值要比上一次的值要小)

时间复杂度

设边数为m,那么时间复杂度就是O(nm),n是迭代的次数

java 复制代码
迭代n次 即循环n次
	遍历所有边,对于每一条边(a,b,v)表示a->b的权值为v
	若从起点到b的距离大于从起点到a的距离+a到b的距离就更新
	这里代码中的体现在于dist[b] = min(dist[b],dist[a]+v])
	没了

代码

java 复制代码
import java.util.Arrays;
import java.util.Scanner;

class Edge{
    int start,end,weight;
    public Edge(int start,int end,int weight){
        this.start = start;
        this.end  = end;
        this.weight = weight;
    }
}
public class Main{
    static int n,m,k,max=(int)1e8;
    static int[] dist;
    static Edge[] edges;
    static int bellman_ford(){
        dist[1] =0;
        for(int i=0;i<k;i++){
        	//这个备份数组的作用是防止发生串联更新
            int[] backup = Arrays.copyOf(dist,dist.length);
            for(Edge item: edges){
                if(dist[item.end]>dist[item.start]+item.weight){
                    dist[item.end] = Math.min(dist[item.end],backup[item.start]+ item.weight);
                }
            }
        }
        if(dist[n]>=max/2)
            return max/2;
        return dist[n];
    }
    public static void main(String[] args) {
        Scanner s=  new Scanner(System.in);
        n = s.nextInt();
        m = s.nextInt();
        k = s.nextInt();
        edges = new Edge[n];
        dist = new int[n+1];
        Arrays.fill(dist,max);
        for(int i=0;i<n;i++)
            edges[i] = new Edge(s.nextInt(),s.nextInt(),s.nextInt());
        int res = bellman_ford();
        if(res==max/2)
            System.out.println("impossible");
        else
            System.out.println(res);
        s.close();
    }
}
相关推荐
此生只爱蛋16 分钟前
【手撕排序2】快速排序
c语言·c++·算法·排序算法
咕咕吖1 小时前
对称二叉树(力扣101)
算法·leetcode·职场和发展
九圣残炎1 小时前
【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目
java·算法·leetcode
lulu_gh_yu1 小时前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
丫头,冲鸭!!!2 小时前
B树(B-Tree)和B+树(B+ Tree)
笔记·算法
Re.不晚2 小时前
Java入门15——抽象类
java·开发语言·学习·算法·intellij-idea
为什么这亚子3 小时前
九、Go语言快速入门之map
运维·开发语言·后端·算法·云原生·golang·云计算
3 小时前
开源竞争-数据驱动成长-11/05-大专生的思考
人工智能·笔记·学习·算法·机器学习
~yY…s<#>3 小时前
【刷题17】最小栈、栈的压入弹出、逆波兰表达式
c语言·数据结构·c++·算法·leetcode
幸运超级加倍~4 小时前
软件设计师-上午题-16 算法(4-5分)
笔记·算法