Day60 图论part10

打印 上一主题 下一主题

主题 1010|帖子 1010|积分 3030

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本日大家会感受到 Bellman_ford 算法系列在差别场景下的应用。

  
建议依然是:一刷的时候,能理解 原理,知道Bellman_ford 办理差别场景的题目 ,照着代码随想录能抄下来代码就好,就算达标。 二刷的时候自己尝试独立去写,三刷的时候 才能有肯定深度理解各个最短路算法。

  

  Bellman_ford 队列优化算法(又名SPFA)

  
代码随想录

  1. import java.util.*;
  2. public class Main{
  3.     public static void main (String[] args) {
  4.         //对所有的边松弛n-1次
  5.         Scanner scanner = new Scanner(System.in);
  6.         int n = scanner.nextInt();
  7.         int m = scanner.nextInt();
  8.         List<List<Edge>> graph = new ArrayList<>(n+1);
  9.         
  10.         for(int i = 0; i <= n; i++){
  11.             graph.add(new ArrayList<>());
  12.         }
  13.         
  14.         for(int i = 0; i < m; i++){
  15.             int start = scanner.nextInt();
  16.             int end = scanner.nextInt();
  17.             int val = scanner.nextInt();
  18.             graph.get(start).add(new Edge(start, end, val));
  19.         }
  20.         
  21.         int[] minDist = new int[n+1];
  22.         Arrays.fill(minDist, Integer.MAX_VALUE);
  23.         minDist[1] = 0;
  24.         
  25.         Deque<Integer> queue = new ArrayDeque<>();
  26.         boolean[] isVisited = new boolean[n+1];
  27.         queue.add(1);
  28.         isVisited[1] = true;
  29.         
  30.         while(!queue.isEmpty()){
  31.             int start = queue.remove();
  32.             //取出队列的时候,要取消标记,这样保证有其他路径对该节点进行更新,我们只要保证节点不被重复加入队列即可
  33.             isVisited[start] = false;
  34.             
  35.             for(Edge edge : graph.get(start)){
  36.                 if(minDist[start] + edge.val < minDist[edge.end]){
  37.                     minDist[edge.end] = minDist[start] + edge.val;
  38.                    if(!isVisited[edge.end]){
  39.                     queue.add(edge.end);
  40.                     isVisited[edge.end] = true;
  41.                     }
  42.                 }
  43.                
  44.             }
  45.         }
  46.         
  47.         if(minDist[n] == Integer.MAX_VALUE){
  48.             System.out.println("unconnected");
  49.         }else{
  50.             System.out.println(minDist[n]);
  51.         }
  52.    
  53.     }
  54. }
  55. class Edge{
  56.     int start;
  57.     int end;
  58.     int val;
  59.    
  60.     public Edge(int start, int end, int val){
  61.         this.start = start;
  62.         this.end = end;
  63.         this.val = val;
  64.     }
  65. }
复制代码
总结
  1.普通的Bellman_ford算法其实是每次都对所有的边都举行一次松懈,但其实但真正有效的松懈,是基于已经盘算过的节点在做的松懈。所以我们每次松懈只必要基于上一次松懈更新过的节点,以该节点作为出发节点对毗连的边就行。那我们就可以使用队列来纪录上一次松懈更新过的节点,把这些节点依次加入到队列内里,然后又取出来处理惩罚。
  2.队列内里存储的是每条边的起点,我们必要根据这些起点,找到边,所以这样传统的邻接表来存储图是最好的List<List<Edge>> graph = new ArrayList<>(n+1);
  3.然后在while循环内里,还有一些地方和之前的处理惩罚不一样,我们必要使用isVisited[]数组来判断节点是否在队列内里&#x

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

水军大提督

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表