【蓝桥杯集训14】Dijkstra求最短路(3 / 3)

目录

朴素版dijkstra算法 —— 稠密图用邻接矩阵存

堆优化版dijkstra算法 —— 稀疏图用邻接表存

1488. 最短距离 – 超级源点

1、dijkstra算法 

2、spfa算法


活动 – AcWing

题目:

给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环,所有边权均为正值

请你求出 1 号点到 n 号点的最短距离,如果无法从 1 号点走到 n 号点,则输出 −1

朴素版dijkstra算法 —— 稠密图用邻接矩阵存

模板:

dist[i]存从点1到i的最短距离  初始化dist[1]=0

循环n次(更新n个点)

{

        每次从1~n点中寻找一个未更新距离起点最近的点

        标记该点

        用该点更新到其他点的最短距离
}

    public static int dijkstra()
    {
        Arrays.fill(dist,0x3f3f3f3f);
        dist[1]=0;
        
        for(int i=0;i<n;i++) //n次循环
        {
            int t=-1;
            //先找出未标记的点中 距离起点最近的点
            for(int j=1;j<=n;j++)
                if(st[j]==0&&(t==-1||dist[j]<dist[t])) 
                    t=j;
            
            st[t]=1;
            
            //用t更新到其他点的最短距离
            for(int j=1;j<=n;j++) dist[j]=Math.min(dist[j],dist[t]+g[t][j]);
        }
        
        return dist[n];
    }
/*
    *道阻且长,行则将至*
    author:Roye_ack
*/
import java.util.*;
import java.io.*;
import java.math.*;
 
class Main
{
    static PrintWriter wt=new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
    static int N=510;
    static int n,m;
    static int[][] g=new int[N][N];
    static int[] dist=new int[N];
    static int[] st=new int[N];
    
    public static int dijkstra()
    {
        Arrays.fill(dist,0x3f3f3f3f);
        dist[1]=0;
        
        for(int i=0;i<n;i++) //n次循环
        {
            int t=-1;
            //先找出未标记的点中 距离起点最近的点
            for(int j=1;j<=n;j++)
                if(st[j]==0&&(t==-1||dist[j]<dist[t])) 
                    t=j;
            
            st[t]=1;
            
            //用t更新到其他点的最短距离
            for(int j=1;j<=n;j++) dist[j]=Math.min(dist[j],dist[t]+g[t][j]);
        }
        
        return dist[n];
    }
    
    public static void main(String[] args) throws IOException
    {
        n=rd.nextInt();
        m=rd.nextInt();
        
        for(int i=1;i<=n;i++)
            Arrays.fill(g[i],0x3f3f3f3f);
        
        while(m-->0)
        {
            int a=rd.nextInt(),b=rd.nextInt(),c=rd.nextInt();
            g[a][b]=Math.min(g[a][b],c); //如果有重边,则取最小的那个边
        }
 
        int t=dijkstra();
        if(t==0x3f3f3f3f) wt.print(-1);
        else wt.print(t);
        wt.flush();
    }
    
    static class rd
    {
        static BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
        static StringTokenizer tk=new StringTokenizer("");
        
        static String nextLine() throws IOException
        {
            return bf.readLine();
        }
        
        static String next() throws IOException
        {
            while(!tk.hasMoreTokens()) tk=new StringTokenizer(bf.readLine());
            return tk.nextToken();
        }
        
        static int nextInt() throws IOException
        {
            return Integer.parseInt(next());
        }
        
        static double nextDouble() throws IOException
        {
            return Double.parseDouble(next());
        }
        
        static long nextLong() throws IOException
        {
            return Long.parseLong(next());
        }
        
        static BigInteger nextBig() throws IOException
        {
            BigInteger d=new BigInteger(rd.nextLine());
            return d;
        }
    }
}
 
class PII
{
    int x,y;
    PII(int x,int y)
    {
        this.x=x;
        this.y=y;
    }
}

堆优化版dijkstra算法 —— 稀疏图用邻接表存

堆优化版dijkstra适合稀疏图

堆优化和朴素版思路一样:

  • 小顶堆每次取距离起点最近的点
  • 若未标记,则用该点更新到其他点的最短距离
/*
    *道阻且长,行则将至*
    author:Roye_ack
*/
import java.util.*;
import java.io.*;
import java.math.*;
 
class Main
{
    static PrintWriter wt=new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
    static int N=150100;
    static int n,m,idx;
    static int[] h=new int[N],e=new int[N],ne=new int[N],w=new int[N];
    static int[] dist=new int[N];
    static int[] st=new int[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 int dijkstra()
    {
        Arrays.fill(dist,0x3f3f3f3f);
        dist[1]=0;
        PriorityQueue<PII> q=new PriorityQueue<>();
        q.offer(new PII(0,1)); //按first排序 所以距离放前边
        
        while(!q.isEmpty())
        {
            var t=q.poll();
            int p=t.y;
            int d=t.x;
            
            if(st[p]==1) continue;
            st[p]=1;
            
            for(int i=h[p];i!=-1;i=ne[i])
            {
                int j=e[i];
                if(dist[j]>d+w[i]) 
                {
                    dist[j]=d+w[i];
                    q.offer(new PII(dist[j],j));
                }
            }
        }
        
        return dist[n];
    }
    
    public static void main(String[] args) throws IOException
    {
        n=rd.nextInt();
        m=rd.nextInt();
        
        Arrays.fill(h,-1);
        
        while(m-->0)
        {
            int a=rd.nextInt(),b=rd.nextInt(),c=rd.nextInt();
            add(a,b,c); //如果有重边,则取最小的那个边
        }
 
        int t=dijkstra();
        if(t==0x3f3f3f3f) wt.print(-1);
        else wt.print(t);
        wt.flush();
    }
    
    static class rd
    {
        static BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
        static StringTokenizer tk=new StringTokenizer("");
        
        static String nextLine() throws IOException
        {
            return bf.readLine();
        }
        
        static String next() throws IOException
        {
            while(!tk.hasMoreTokens()) tk=new StringTokenizer(bf.readLine());
            return tk.nextToken();
        }
        
        static int nextInt() throws IOException
        {
            return Integer.parseInt(next());
        }
        
        static double nextDouble() throws IOException
        {
            return Double.parseDouble(next());
        }
        
        static long nextLong() throws IOException
        {
            return Long.parseLong(next());
        }
        
        static BigInteger nextBig() throws IOException
        {
            BigInteger d=new BigInteger(rd.nextLine());
            return d;
        }
    }
}
 
class PII implements Comparable<PII>
{
    public int x;
    public int y;
    public PII(int x,int y)
    {
        this.x=x;
        this.y=y;
    }
    public int compareTo(PII o)
    {
        return Integer.compare(x,o.x);
    }
    
}

1488. 最短距离 – 超级源点

1488. 最短距离 – AcWing题库

题目:

n个村庄有m条无向道路,每条道路长c

有k个村庄有商店

给q个询问,输出qi点到商店的最近距离

思路:

设置了一个超级源点,该源点到每个商店的距离都是0

因此从这个点就可以代表所有的商店,只需要计算当前点到这个超级源点的最短路即可

1、dijkstra算法 

/*
    *道阻且长,行则将至*
    author:Roye_ack
*/
import java.util.*;
import java.io.*;
import java.math.*;
 
class Main
{
    static PrintWriter wt=new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
    static int N=2000000,M=2*N;
    static int n,m,idx;
    static int[] h=new int[N],e=new int[N],ne=new int[N],w=new int[N];
    static int[] dist=new int[N];
    static int[] st=new int[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 dijkstra()
    {
        Arrays.fill(dist,0x3f3f3f3f);
        PriorityQueue<PII> q=new PriorityQueue<>();
        q.offer(new PII(0,0));
        dist[0]=0;
        
        while(!q.isEmpty())
        {
            var t=q.poll();
            int ver=t.y;
            int d=t.x;
            
            if(st[ver]==1) continue;
            st[ver]=1;
            
            for(int i=h[ver];i!=-1;i=ne[i])
            {
                int j=e[i];
                if(dist[j]>d+w[i])
                {
                    dist[j]=d+w[i];
                    q.offer(new PII(dist[j],j));
                }
            }
        }
    }
    
    public static void main(String[] args) throws IOException
    {
        n=rd.nextInt();
        m=rd.nextInt();
        
        Arrays.fill(h,-1);
        
        while(m-->0)
        {
            int a=rd.nextInt(),b=rd.nextInt(),c=rd.nextInt();
            add(a,b,c);
            add(b,a,c);
        }
 
        int k=rd.nextInt();
        while(k-->0)
        {
            int x=rd.nextInt();
            add(0,x,0);  //设置一个超级源点,每个商店到这个源点距离均为0
            //即超级源点代表所有商店,因此只要计算每个询问到超级源点的最短距离即可
        }
        
        dijkstra();
        
        int que=rd.nextInt();
        while(que-->0)
        {
            int qq=rd.nextInt();
            wt.println(dist[qq]);
        }
        wt.flush();
    }
    
    static class rd
    {
        static BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
        static StringTokenizer tk=new StringTokenizer("");
        
        static String nextLine() throws IOException
        {
            return bf.readLine();
        }
        
        static String next() throws IOException
        {
            while(!tk.hasMoreTokens()) tk=new StringTokenizer(bf.readLine());
            return tk.nextToken();
        }
        
        static int nextInt() throws IOException
        {
            return Integer.parseInt(next());
        }
        
        static double nextDouble() throws IOException
        {
            return Double.parseDouble(next());
        }
        
        static long nextLong() throws IOException
        {
            return Long.parseLong(next());
        }
        
        static BigInteger nextBig() throws IOException
        {
            BigInteger d=new BigInteger(rd.nextLine());
            return d;
        }
    }
}
 
class PII implements Comparable<PII>
{
    public int x;
    public int y;
    public PII(int x,int y)
    {
        this.x=x;
        this.y=y;
    }
    public int compareTo(PII o)
    {
        return Integer.compare(x,o.x);
    }
    
}

2、spfa算法

/*
    *道阻且长,行则将至*
    author:Roye_ack
*/
import java.util.*;
import java.io.*;
import java.math.*;
 
class Main
{
    static PrintWriter wt=new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
    static int N=2000000,M=2*N;
    static int n,m,idx;
    static int[] h=new int[N],e=new int[N],ne=new int[N],w=new int[N];
    static int[] dist=new int[N];
    static int[] st=new int[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,0x3f3f3f3f);
        q.offer(0);
        st[0]=1;
        dist[0]=0;
        
        while(!q.isEmpty())
        {
            var t=q.poll();
            st[t]=0;
            
            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]==0)
                    {
                        q.offer(j);
                        st[j]=1;
                    }
                }
            }
        }
            
    }
    
    public static void main(String[] args) throws IOException
    {
        n=rd.nextInt();
        m=rd.nextInt();
        
        Arrays.fill(h,-1);
        
        while(m-->0)
        {
            int a=rd.nextInt(),b=rd.nextInt(),c=rd.nextInt();
            add(a,b,c);
            add(b,a,c);
        }
 
        int k=rd.nextInt();
        while(k-->0)
        {
            int x=rd.nextInt();
            add(0,x,0);  //设置一个超级源点,每个商店到这个源点距离均为0
            //即超级源点代表所有商店,因此只要计算每个询问到超级源点的最短距离即可
        }
        
        spfa();
        
        int que=rd.nextInt();
        while(que-->0)
        {
            int qq=rd.nextInt();
            wt.println(dist[qq]);
        }
        wt.flush();
    }
    
    static class rd
    {
        static BufferedReader bf=new BufferedReader(new InputStreamReader(System.in));
        static StringTokenizer tk=new StringTokenizer("");
        
        static String nextLine() throws IOException
        {
            return bf.readLine();
        }
        
        static String next() throws IOException
        {
            while(!tk.hasMoreTokens()) tk=new StringTokenizer(bf.readLine());
            return tk.nextToken();
        }
        
        static int nextInt() throws IOException
        {
            return Integer.parseInt(next());
        }
        
        static double nextDouble() throws IOException
        {
            return Double.parseDouble(next());
        }
        
        static long nextLong() throws IOException
        {
            return Long.parseLong(next());
        }
        
        static BigInteger nextBig() throws IOException
        {
            BigInteger d=new BigInteger(rd.nextLine());
            return d;
        }
    }
}
 
class PII implements Comparable<PII>
{
    public int x;
    public int y;
    public PII(int x,int y)
    {
        this.x=x;
        this.y=y;
    }
    public int compareTo(PII o)
    {
        return Integer.compare(x,o.x);
    }
    
}