Java中的图论3 —— Floyd

Java中的Floyd - 260331

  • [Floyd ------ 多源最短路](#Floyd —— 多源最短路)
  • [例题1(FROM 洛谷 B3647)](#例题1(FROM 洛谷 B3647))
  • [例题2 (FROM 洛谷 P2910)](#例题2 (FROM 洛谷 P2910))
  • 图论的总结
  • [图论提升 ------ 反向建图](#图论提升 —— 反向建图)

图论第一章 ->Java中的 Dijkstra 算法

图论第二章 ->Java中的图论2------Kruskal算法

图论第三章 -> 本章

Floyd ------ 多源最短路

如果说之前的 Dijkstra 算法是求最短路,那么 Floyd 算法就是求很多对点之间的最短路 ,但是他有个弊端,就是他是靠循环完成优化的,所以不可以在大数据情况下使用,如果数据很大,建议将Dijkstra封装成函数,多跑几次函数。

  • 原理:该算法的原理是,找图中是否有一个节点 k,使得节点 i 到节点 j ,经过节点 k 时比直接从 i 到 j 要 "近"(就是指总权重小)。

例题1(FROM 洛谷 B3647)

注意这里是 B3647,不是P3647。

代码实现

java 复制代码
import java.util.*;
public class Main{
    static int INF = 0x3f3f3f3f;
    public static void main(String [] args){
        Scanner input = new Scanner (System.in);
        int n = input.nextInt();
        int m = input.nextInt();
        int [][] dist = new int [n+1][n+1];
        for(int i=1;i<=n;i++)
           for(int j=1;j<=n;j++)
               dist[i][j] = (i==j)?0:INF;
        
        for(int i=0;i<m;i++){
            int u = input.nextInt();
            int v = input.nextInt();
            int w = input.nextInt();
           if(w<dist[u][v]){
               dist[u][v] = w;
               dist[v][u] = w;
           }
        }
 //------------------------------------------------ Floyd的核心循环------------------------------------------------------------------------------
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    if(dist[i][k] != INF && dist[k][j] != INF)
                        dist[i][j]=Math.min(dist[i][j],
                            dist[i][k]+dist[k][j]);
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        for(int i=1;i<=n;i++){
             for(int j=1;j<=n;j++)
                System.out.print(dist[i][j] + " ");
            System.out.println();
        }
    }
}

例题2 (FROM 洛谷 P2910)

代码实现

这个和之前的区别就多了一个累和

java 复制代码
import java.util.*;
public class Main{
    static int INF = 0x3f3f3f3f;
    public static void main(String [] args){
        Scanner input = new Scanner (System.in);
        int n = input.nextInt();
        int m = input.nextInt();
        int [] kk = new int [m+1];
        for(int i=0;i<m;i++)
            kk[i] = input.nextInt();
        int [][] dang = new int [n+1][n+1];
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                dang[i][j] = input.nextInt();
//---------------------------------------------------------------------------------------------------------核心循环------------------------------------------------------------------------------------------------------------------------
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    if(dang[i][j] != 0 && dang[i][j] != 0)
                        dang[i][j] = Math.min(dang[i][j],dang[i][k]+dang[k][j]);
//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        long sum = 0;
        for(int i=0;i<m-1;i++)
            sum += dang[kk[i]][kk[i+1]];
        System.out.print(sum);
    }
}

图论的总结

  • Dijkstra 算法:
    解决问题:单源最短路(一个起点到所有点的最短距离)
    实现方式:最小堆(优先队列)+ BFS
  • Floyd 算法:
    解决问题:多源最短路(很多对点之间的最短路)
    实现方法:二维数组 + 三重循环
  • Kruskal 算法:
    解决问题:最小生成树/图(MST)
    实现方法:二维数组 + 并查集

图论提升 ------ 反向建图

思路

我最初的想法是用Floyd算法,预处理任意两点之间的最短距离,并用二维数组接收,但是这种方式的计算量是巨大的,并不适合本题。所以我又想到了Dijkstra算法,既然他属于单源最短路,我们可以用这个算法,但是他要一去一回,我们要使用两遍 Dijkstra ,所以我们将其封装成函数。同时,建一正一反两个图,同时处理,这样得到结果是最快的。

代码实现

java 复制代码
import java.util.*;
import java.io.*;

public class Main{
    static int n;
    static final long INF = (long) 1e15; 
    static BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    
    public static void main(String [] args) throws IOException{
        n = Integer.parseInt(next());
        int m = Integer.parseInt(next());
        List<ArrayList<int []>> list1 = new ArrayList<>(n+1);
        List<ArrayList<int []>> list2 = new ArrayList<>(n+1);
        for(int i=0;i<=n;i++){
            list1.add(new ArrayList<>());
            list2.add(new ArrayList<>());
        }
        
        for(int i=0;i<m;i++){
            int u = Integer.parseInt(next());
            int v = Integer.parseInt(next());
            int w = Integer.parseInt(next());
            list1.get(u).add(new int []{v,w});//正图
            list2.get(v).add(new int []{u,w});//反图
        }
        
        long [] dist1 = dij(list1,1);
        long [] dist2 = dij(list2,1);
        long ans = 0;
        for(int i=2;i<=n;i++)
            ans += dist1[i] + dist2[i];
        System.out.print(ans);
    }
    static long [] dij(List<ArrayList<int []>> l,int begin){
        long [] dist = new long [n+1];
        Arrays.fill(dist,INF);
        dist [begin] = 0;
        PriorityQueue <long []> PQ = new PriorityQueue<>((a,b)->Long.compare(a[0],b[0]));
        PQ.offer(new long [] {dist[begin],begin});
        while(!PQ.isEmpty()){
            long [] cur = PQ.poll();
            long d = cur[0];
            int u = (int)cur[1];
            if(d!=dist[u]) continue;
            for(int [] e : l.get(u)){
                int v = e[0];
                int w = e[1];
                if(dist[u] + w < dist[v]){
                    dist[v] = dist[u] + w;
                    PQ.offer(new long[]{dist[v],v});
                }
            }
        }
        return dist;
    }
    static String next() throws IOException{
        while(st == null || !st.hasMoreTokens()){
            String str = bf.readLine();
            if(str == null) return null;
            st = new StringTokenizer(str);
        }
        return st.nextToken();
    }
}
相关推荐
心之语歌2 小时前
Vue2 data + Vue3 ref/reactive 核心知识点总结
开发语言·前端·javascript
程序员小寒2 小时前
JavaScript设计模式(六):职责链模式实现与应用
java·javascript·设计模式
关于不上作者榜就原神启动那件事2 小时前
@Transactional事务失效总结
java·开发语言·jvm
jaysee-sjc2 小时前
【项目三】用GUI编程实现局域网群聊软件
java·开发语言·算法·安全·intellij-idea
无名-CODING2 小时前
Java 爬虫高级技术:反反爬策略与分布式爬虫实战
java·分布式·爬虫
jonyleek2 小时前
JVS物联网应用中控制器的四大职责和设备接入全流程
java·struts·servlet·私有化部署
csdn2015_2 小时前
java 将 List<Map<String,Object>> 类型里面的值转换为List<String>
java·windows·list
怀化纱厂球迷2 小时前
android车载应用动画-仿窗帘式下拉显示!Android 实现跟手裁剪动画 + RecyclerView 列表展示
android·java
牢七2 小时前
jfinal_cms-v5.1.0 白盒 nday
开发语言·python