Java中的图论2——Kruskal算法

Java中的Kruskal------最小生成树

  • [Kruskal ------ 最小生成树/图](#Kruskal —— 最小生成树/图)
  • [例题1(FROM 洛谷 P3366)](#例题1(FROM 洛谷 P3366))

图论的第一篇是前一章的 -> Java中的 Dijkstra 算法,还打算写一个Floyd,在图论的最后一章会总结三种算法在什么情况下适合使用,以及使用方法,加深记忆。

Kruskal ------ 最小生成树/图

学过离散数学的应该知道什么是最小生成树/图,假设有n个节点,画n-1条边使得该树/图最后的总权重最小的,就是最小生成。Kruskal 算法其实是图论思想和并查集 的结合。并查集不会的可以去补一下 ->Java中的并查集

例题1(FROM 洛谷 P3366)


这就是个模板题,没有什么思路,可以直接看代码

代码实现

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

public class Main{
    static int [] p;
    static BufferedReader bf  = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    
    public static void main(String [] args) throws IOException{
        int n = Integer.parseInt(next());
        int m = Integer.parseInt(next());
        int [][] e = new int [m][3];//{u,v,w};
        for(int i=0;i<m;i++){
            int u = Integer.parseInt(next());
            int v = Integer.parseInt(next());
            int w = Integer.parseInt(next());
            e[i] = new int []{u,v,w};
        }
        Arrays.sort(e,(a,b)->a[2]-b[2]);//将接收到的边按照权重从小到大排序
        
        p = new int [n+1];
        for(int i=1;i<=n;i++)
            p[i] = i;
            
        long ans = 0;//结果
        int count  = 0;//边的个数
        for(int [] E:e){
            int u = E[0];
            int v = E[1];
            int w = E[2];
            if(find(u) != find(v)){//如果没在最小生成图里
                union(u,v);//加进去
                ans += w;//结果加上该边的权重
                count++;//边数加一
                if(count == n-1) break;//如果已经找到了n-1条边,提前结束,剪枝
            }
        }
        if(count < n-1)//如果找到的边不够,说明该图不连通
            System.out.print("orz");
        else System.out.print(ans);
    }
    static int find(int x){
        if(x == p[x]) return x;
        else return p[x] = find(p[x]);
    }
    static void union(int x,int y){
        int rx = find(x);
        int ry = find(y);
        if(rx != ry)
            p[rx] = ry;
    }
    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();
    }
}

进阶版: 洛谷 P2820,自行练习吧,代码我贴这里了:

java 复制代码
import java.util.*;
public class Main{
    static int [] p;
    public static void main(String [] args){
        Scanner input = new Scanner (System.in);
        int n = input.nextInt();
        int k = input.nextInt();
        int [][] f = new int [k][3];
        long sumM = 0;
        for(int i=0;i<k;i++){
            f[i][0] = input.nextInt();//i
            f[i][1] = input.nextInt();//j
            f[i][2] = input.nextInt();//m
            sumM += f[i][2];
        }
        Arrays.sort(f,(a,b)->a[2]-b[2]);
        p = new int [n+1];
        for(int i=0;i<=n;i++)
            p[i] = i;
        
        long ans = 0;
        int count = 0;
        for(int i=0;i<k;i++){
            int u = f[i][0];
            int v = f[i][1];
            int w = f[i][2];
            if(find(u) != find(v)){
                union(u,v);
                ans += w;
                count ++;
                if(count == n-1) break;
            }
        }
        System.out.print(sumM-ans);
    }
    static int find(int x){
        if(x == p[x]) return x;
        else  return p[x] = find(p[x]);
    }
    static void union(int x,int y){
        int rx = find(x);
        int ry = find(y);
        if(rx != ry)
            p[rx] = ry;
    }
}

只要学好并查集 so easy

相关推荐
麻瓜生活睁不开眼7 小时前
Android16修改全局桌面视图边框四直角显示为弧边圆角
android·java·深度学习
dear_bi_MyOnly7 小时前
【MyBatis 操作数据库】
java·数据库·学习·mybatis·学习方法
2601_953720828 小时前
【计算机毕业设计】基于Spring Boot的心理健康咨询与评测系统的设计与实现
java·spring boot·后端
丈剑走天涯9 小时前
JDK 17 正式特性
java·开发语言
圣光SG9 小时前
Java操作题练习(七)
java·开发语言·算法
Cx330_FCQ10 小时前
Tmux使用
服务器·git·算法
@航空母舰11 小时前
SpringBoot通过Map实现天然的策略模式
java·spring boot·后端
Co_Hui11 小时前
Java 并发编程
java
拳里剑气11 小时前
C++算法:多源BFS
c++·算法·宽度优先·多源bfs
ysa05103012 小时前
【板子】短序列dp(换成维护更小常数维度的dp)
c++·笔记·算法·板子