图论记录之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();
    }
}
相关推荐
core5128 分钟前
SVD 算法详解:给数据做个“CT扫描”
算法·svd·图片压缩·目标函数
有一个好名字10 分钟前
力扣-确定两个字符串是否接近
算法·leetcode·职场和发展
小O的算法实验室40 分钟前
2024年ESWA SCI1区TOP,基于自适应模糊惩罚的多约束无人机路径规划状态转移算法,深度解析+性能实测
算法·论文复现·智能算法·智能算法改进
一条大祥脚1 小时前
Codeforces Round 1072 (Div. 3) 树形背包|线段树二分|区间并查集维护区间合并/set维护区间分裂
算法·深度优先·图论
Xの哲學1 小时前
Linux SKB: 深入解析网络包的灵魂
linux·服务器·网络·算法·边缘计算
无限进步_1 小时前
【C语言&数据结构】二叉树遍历:从前序构建到中序输出
c语言·开发语言·数据结构·c++·算法·github·visual studio
CodeByV1 小时前
【算法题】哈希
算法·哈希算法
天赐学c语言1 小时前
1.14 - 用栈实现队列 && 对模板的理解以及模板和虚函数区别
c++·算法·leecode
高洁011 小时前
AI智能体搭建(3)
人工智能·深度学习·算法·数据挖掘·知识图谱
不知名XL2 小时前
day24 贪心算法 part02
算法·贪心算法