图论记录之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();
    }
}
相关推荐
Indigo_code1 小时前
【数据结构】【顺序表算法】 删除特定值
数据结构·算法
阿史大杯茶2 小时前
Codeforces Round 976 (Div. 2 ABCDE题)视频讲解
数据结构·c++·算法
LluckyYH2 小时前
代码随想录Day 58|拓扑排序、dijkstra算法精讲,题目:软件构建、参加科学大会
算法·深度优先·动态规划·软件构建·图论·dfs
转调2 小时前
每日一练:地下城游戏
开发语言·c++·算法·leetcode
不穿格子衬衫3 小时前
常用排序算法(下)
c语言·开发语言·数据结构·算法·排序算法·八大排序
wdxylb3 小时前
使用C++的OpenSSL 库实现 AES 加密和解密文件
开发语言·c++·算法
aqua35357423583 小时前
蓝桥杯-财务管理
java·c语言·数据结构·算法
CV金科3 小时前
蓝桥杯—STM32G431RBT6(IIC通信--EEPROM(AT24C02)存储器进行通信)
stm32·单片机·嵌入式硬件·算法·蓝桥杯
sewinger3 小时前
区间合并算法详解
算法
XY.散人4 小时前
初识算法 · 滑动窗口(1)
算法