算法模板之SPFA

Bellman-Ford可以處理帶負權圖的單源最短路問題。(帶負勸環的圖,沒法求出單源最短路)java

Bellman-Ford的主要思想以下:數組

​ 給定一張有向圖,若對於圖中的某一條邊(x,y,z),有\(dist[y]<=dist[x]+z\)成立,則稱該邊知足三角不等式。若全部邊都知足三角不等式,則dist數組就是所求最短路優化

Bellman-Ford的流程以下:spa

  1. 掃描全部的邊(x,y,z),若dist[y] > dist[x] + z , 則用dist[x] + z 更新 dist[y]code

  2. 重複上述步驟,直到沒有更新操做發生。隊列

SPFA是在上述基礎上,使用隊列進行優化,核心思想就是說:只有已經被鬆弛的點,纔可能去鬆弛其餘的點。咱們能夠經過隊列來維護已經被鬆弛的點,那麼咱們就不須要每次遍歷全部的邊了。class

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;
    }
}
相關文章
相關標籤/搜索