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;
        }
    }
    
  • 相关阅读:
    HDU 6143 Killer Names【dp递推】【好题】【思维题】【阅读题】
    HDU 6143 Killer Names【dp递推】【好题】【思维题】【阅读题】
    POJ 3974 Palindrome【manacher】【模板题】【模板】
    POJ 3974 Palindrome【manacher】【模板题】【模板】
    HDU 6127 Hard challenge【计算机几何】【思维题】
    HDU 6127 Hard challenge【计算机几何】【思维题】
    HDU 6129 Just do it【杨辉三角】【思维题】【好题】
    HDU 6129 Just do it【杨辉三角】【思维题】【好题】
    HDU 3037 Saving Beans【Lucas定理】【模板题】【模板】【组合数取余】
    8.Math 对象
  • 原文地址:https://www.cnblogs.com/backkom-buaa/p/13855313.html
Copyright © 2011-2022 走看看