zoukankan      html  css  js  c++  java
  • 算法模板之SPFA

    Bellman-Ford能够处理带负权图的单源最短路问题。(带负劝环的图,无法求出单源最短路)

    Bellman-Ford的主要思想如下:

    ​ 给定一张有向图,若对于图中的某一条边(x,y,z),有(dist[y]<=dist[x]+z)成立,则称该边满足三角不等式。若所有边都满足三角不等式,则dist数组就是所求最短路

    Bellman-Ford的流程如下:

    1. 扫描所有的边(x,y,z),若dist[y] > dist[x] + z , 则用dist[x] + z 更新 dist[y]

    2. 重复上述步骤,直到没有更新操作发生。

    SPFA是在上述基础上,使用队列进行优化,核心思想就是说:只有已经被松弛的点,才可能去松弛其他的点。我们可以通过队列来维护已经被松弛的点,那么我们就不需要每次遍历所有的边了。

    C++ 板子 Bellman-Ford & SPFA

    /**
      链式前向星来存图
      int e[MAX_EDGE][2],hd[MAX_N],nxt[MAX_EDGE],top;
      void add(int u,int v,int w){
      	e[++top][0]=v;
      	e[top][1]=w;
      	nxt[top]=hd[u];
      	hd[u]=top;
      }
    **/
    // Bellman-Ford
    while(true){
      	bool f=false;
        for(int i=1;i<=n;i++) {
            for(int ev=hd[i];ev;ev=nxt[ev]){
                int v=e[ev][0],w=e[ev][1];
                if(dis[i]+w<dis[v]) {
                    dis[v]=dis[i]+w;	
        			f=true;
                }
            }
        }
        if(f==false) break;
    }
    
    //SPFA
    queue<int>q;
    q.push(start);
    while(q.size()>0){
    	int u=q.front();
        q.pop();
        vis[u]=0;
        
        for(int ev=hd[u];ev;ev=next[ev]){
            int v=e[ev][0],w=e[ev][1];
            if(dis[u]+w<dis[v]){
             	dis[v]=dis[u]+w;
                if(!vis[v]) {
                    vis[v]=1;q.push(v);
                }
            }
        }
    }
    
    
    
    
    

    Java 板子 SPFA

    /*
    	题目链接:https://ac.nowcoder.com/acm/problem/14369?&headNav=www
        spfa的最短路的写法
        链式前向星   
    */
    import java.util.*;
    public class Main {
        
        private static int e[][] = new int[202000][2];
        private static int nxt[] = new int[220000];
        private static int hd[] = new int [20020];
        private static int top = 0;
        
        private static int n,m;
        public static void main(String[] args) {
            
            Scanner in = new Scanner(System.in);
            n = in.nextInt();
            m = in.nextInt();
            for(int i=1;i<=m;i++) {
                add(in.nextInt(),in.nextInt(),in.nextInt());
            }
            
            int dis[] = new int[n+1];
            int vis[] = new int[n+1];
            Arrays.fill(dis,Integer.MAX_VALUE);
            dis[1]=0;
            
            //可以按照点来遍历,也可以按照边来遍历
            //只有被松弛的点,才可能去松弛其他的点。spfa的本质就是这个    
            Queue<Integer>q = new LinkedList<Integer>();
            q.offer(1);
            while(!q.isEmpty()) {
                int u = q.peek();
                q.poll();
                vis[u] = 0;
                
                for(int i=hd[u];i>0;i=nxt[i]){
                    int v=e[i][0],w=e[i][1];
                    if(dis[u]+w < dis[v]){
                        dis[v] = dis[u]+w;
                        if(vis[v] == 0) {
                            q.offer(v);
                            vis[v] = 1;
                        }
                    }
                }
            }
            
            for(int i=2;i<=n;i++) {
                System.out.println(dis[i]);
            }
            
            return;
        }
        
        private static void add(int u,int v,int w){
            e[++top][0] = v;
            e[top][1] = w;
            nxt[top] = hd[u];
            hd[u] = top;
        }
    }
    
  • 相关阅读:
    git常用命令及常见问题解析
    如何让一个sprite绕一个点旋转,同时又可以实现指定旋转角度并慢慢停下的效果
    webpack打包,同时将ES6转为ES5,初探
    测试网站接口,nginx篇
    Phaserjs V2的state状态解析及技巧
    Phaserjs怎样用ES6开发游戏
    PIXI屏幕自适应以及强制横屏
    CSS性能优化新属性:will-change
    div,css&table布局有哪些区别
    防止js全局变量污染方法总结
  • 原文地址:https://www.cnblogs.com/backkom-buaa/p/13855313.html
Copyright © 2011-2022 走看看