Spfa基础算法

大家好 我是寸铁 希望这篇题解对你有用,麻烦动动手指点个赞或关注,感谢您的关注

不清楚蓝桥杯考什么的点点下方

考点秘籍

想背纯享模版的伙伴们点点下方

蓝桥杯省一你一定不能错过的模板大全(第一期)

蓝桥杯省一你一定不能错过的模板大全(第二期)

蓝桥杯省一你一定不能错过的模板大全(第三期)

蓝桥杯省一你一定不能错过的模板大全(第四期)!!!

想背注释模版的伙伴们点点下方

蓝桥杯必背第一期

蓝桥杯必背第二期

往期精彩回顾

蓝桥杯上岸每日N题 第一期(一)!!!

蓝桥杯上岸每日N题第一期(二)!!!

蓝桥杯上岸每日N题第一期(三)!!!

蓝桥杯上岸每日N题第二期(一)!!!

蓝桥杯上岸每日N题第三期(一)!!!

蓝桥杯上岸每日N题 第四期(最少刷题数)!!!

蓝桥杯上岸每日N题 第五期(山)!!!

蓝桥杯上岸每日N题 第六期(求阶乘)!!!

蓝桥杯上岸每日N题 第七期(小猫爬山)!!!

蓝桥杯上岸每日N题 第八期 (全球变暖)!!!

操作系统期末题库 第九期(完结)

LeetCode Hot100 刷题(第三期)

idea创建SpringBoot项目报错解决方案

数据库SQL语句(期末冲刺)

想看JavaB组填空题的伙伴们点点下方

填空题

竞赛干货

算法竞赛字符串常用操作大全

蓝桥杯上岸必刷!!!(模拟/枚举专题)

蓝桥杯上岸必背!!! (第三期 DP)

蓝桥杯上岸必背!!!(第四期DFS)

蓝桥杯上岸必背!!!(第五期BFS)

蓝桥杯上岸必背!!!(第六期树与图的遍历)

蓝桥杯上岸必背!!!(第七期 最短路算法)

蓝桥杯上岸必背!!!(第八期 简单数论)

蓝桥杯上岸必刷!!!(进制、数位专题)

蓝桥杯上岸考点清单 (冲刺版)!!!

蓝桥杯上岸必背模板 (纯享版)

题目

spfa求最短路

做法

用队列来维护搜索的顺序,一层一层往下搜,相当于BFS
每次用当前搜的这一轮的最短距离去更新下一轮的最短距离

注意

初始化dist数组为INF,这样做的目的是便于去判断是否走到n存在最短路
st[]数组存的是当前在队列中的元素,所以在每次入队时,可以将元素置为true,表示在队列中。
出队时,再将元素置为false,表示不在队列中,这样就避免了更新重复元素的最短路

spfa模板

import java.util.*;
public class Main{
    static int N=100010,n,m,idx,INF=0x3f3f3f3f;
    static int []h=new int[N],e=new int[N],ne=new int[N],w=new int[N];
    static int []q=new int[N];
    static int []dist=new int[N];
    static boolean []st=new boolean[N];
    public static void add(int a,int b,int c){
        e[idx]=b;
        w[idx]=c;
        ne[idx]=h[a];
        h[a]=idx++;
    }
    public static void spfa(){
        Queue<Integer>q=new LinkedList<>();
        Arrays.fill(dist,INF);
        q.offer(1);
        dist[1]=0;
        st[1]=true;
        while(!q.isEmpty()) {
        	int t=q.poll();
        	st[t]=false;
        	for(int i=h[t];i!=-1;i=ne[i]) {
        		int j=e[i];
        		if(dist[j]>dist[t]+w[i]) {
        			dist[j]=dist[t]+w[i];
        			//满足这个条件的才需要入队
                   //写在外面就会将不满足这个条件的都入队
        			if(!st[j]) {
        				q.offer(j);
        				st[j]=true;
        			}
        		}
        		
        	}
        	
        }
        if(dist[n]==INF)System.out.println("impossible");
        else System.out.println(dist[n]);
        
    }
    
    public static void main(String []args){
        Scanner in = new Scanner(System.in);
        n=in.nextInt();
        m=in.nextInt();
        Arrays.fill(h, -1);
        while(m-->0) {
        	int a=in.nextInt();
        	int b=in.nextInt();
        	int c=in.nextInt();
        	add(a, b, c);
        }
        spfa();
    }
    
    
}

spfa判断负环

思想

用队列来维护搜索的顺序,一层一层往下搜,相当于BFS
每次用当前搜的这一轮的最短距离去更新下一轮的最短距离

代码解析

cnt[j]=cnt[t]+1;
记录走到当前这个点所经过(用到)的边数

if(cnt[j]>=n)return true;
解释:走了n个点对应的是n-1条边,如果说边数大于等于n则说明是至少n+1个点。
但是我们最多只有n个点,说明必定有部分点重复,形成回路。
由于比较的是最短距离,所以该回路必定是负权回路

st[]数组存的是当前在队列中的元素,所以在每次入队时,可以将元素置为true,表示在队列中。 出队时,再将元素置为false,表示不在队列中,这样就避免了更新重复元素的最短路

spfa判断负环

//spfa()判断负环
import java.util.*;
public class Main{
    static int N=2010,M=10010,n,m,idx;
    static int e[]=new int [M];
    static int ne[]=new int[M];
    static int h[]=new int [N];
    static int w[]=new int[M];
    static int dist[]=new int [N];
    static int cnt[]=new int[N];
    static boolean st[]=new boolean[N];
    //存的是否在当前的队列中
    public static void add(int a,int b ,int c){
        e[idx]=b;
        w[idx]=c;
        ne[idx]=h[a];
        h[a]=idx++;
    }
    public static boolean spfa(){
        Queue<Integer>q=new LinkedList<>();
        //用队列来维护搜索的顺序,一层一层往下搜,相当于BFS。
        //每次用当前搜的这一轮的最短距离去更新下一轮的最短距离。
        for(int i=1;i<=n;i++){
            q.offer(i);
            st[i]=true;
        }
        //由于求的是图中的负环不是从1号点到n号点的负环
        //所以每个点都需要入队,并置为true。
        while(!q.isEmpty()){
            int t=q.poll();
            st[t]=false;
            for(int i=h[t];i!=-1;i=ne[i]){
                int j=e[i];
                if(dist[j]>dist[t]+w[i]){
                    dist[j]=dist[t]+w[i];
                    cnt[j]=cnt[t]+1;
                //记录走到当前这个点所用的边数
                if(cnt[j]>=n)return true;
                //走了n个点对应的是n-1条边
    //如果说边数大于等于n则说明是至少是n+1个点
    //但是我们最多只有n个点,说明必定有些点重复,形成回路。
    //但是由于比较的是最短距离,所以该回路必定是负权回路。
                
                //满足这个条件的才需要入队
                //写在外面就会将不满足这个条件的都入队
                if(!st[j]){
                    q.offer(j);
                    st[j]=true;
                }
                
                
            }
            
        }
        }
        return false;
        
        
    }
    public static void main(String []args){
        Scanner in = new Scanner(System.in);
        n=in.nextInt();
        m=in.nextInt();
        Arrays.fill(h,-1);
        //初始化h[]数组为空
        while(m-->0){
            int a=in.nextInt();
            int b=in.nextInt();
            int c=in.nextInt();
            add(a,b,c);
            
            
        }
        if(spfa())System.out.println("Yes");
        else System.out.println("No");
         
        
    }
}

代码

import java.util.*;
public class Main{
    static int N=2010,M=10010,n,m,idx;
    static int e[]=new int [M];
    static int ne[]=new int[M];
    static int h[]=new int [M];
    static int w[]=new int[M];
    static int dist[]=new int [N];
    static int cnt[]=new int[N];
    static boolean st[]=new boolean[N];
    public static void add(int a,int b ,int c){
        e[idx]=b;
        w[idx]=c;
        ne[idx]=h[a];
        h[a]=idx++;
    }
    public static boolean spfa(){
        Queue<Integer>q=new LinkedList<>();
        for(int i=1;i<=n;i++){
            q.offer(i);
            st[i]=true;
        }
        while(!q.isEmpty()){
            int t=q.poll();
            st[t]=false;
            for(int i=h[t];i!=-1;i=ne[i]){
                int j=e[i];
                if(dist[j]>dist[t]+w[i]){
                    dist[j]=dist[t]+w[i];
                    cnt[j]=cnt[t]+1;
                
                if(cnt[j]>=n)return true;
                if(!st[j]){
                    q.offer(j);
                    st[j]=true;
                }
                
                
            }
            
        }
        }
        return false;
        
        
    }
    public static void main(String []args){
        Scanner in = new Scanner(System.in);
        n=in.nextInt();
        m=in.nextInt();
        Arrays.fill(h,-1);
        while(m-->0){
            int a=in.nextInt();
            int b=in.nextInt();
            int c=in.nextInt();
            add(a,b,c);
            
            
        }
        if(spfa())System.out.println("Yes");
        else System.out.println("No");
         
        
    }
}

你可能感兴趣的:(蓝桥杯上岸,算法,蓝桥杯,java,leetcode,刷题,spfa,最短路)