图论:最小生成树kruscarl+并查集算法

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    static Scanner in=new Scanner(System.in);

    //并查集
    static int n;
    static int[] parent;
    static void init(){
        for (int i = 1; i <= n; i++) {
            parent[i]=i;
        }
    }
    static int find(int a){
        if (parent[a]==a) {
            return a;
        }
        parent[a]=find(parent[a]);
        return parent[a];
    }
    static void join(int a,int b){
        a=find(a);
        b=find(b);
        if (a==b){
            return;
        }
        parent[a]=b;
    }
    static boolean isSame(int a,int b){
        return find(a)==find(b);
    }

    //存边的类
    static class Edge{
        int u,v,w;
        public Edge(int u, int v, int w) {
            this.u = u;
            this.v = v;
            this.w = w;
        }
    }

    public static void main(String[] args) {
        int m;
       n=in.nextInt();
       m=in.nextInt();
       parent=new int[n+1];
       init();
       //存边
       Edge[] edges=new Edge[m];
        for (int i = 0; i < m; i++) {
            int u=in.nextInt();
            int v=in.nextInt();
            int w=in.nextInt();
            edges[i]=new Edge(u,v,w);
        }
        //排序,(a,b)->a.w-b.w表示从小到大,若b.w-a.w表示从大到小
        Arrays.sort(edges, (a,b)->a.w-b.w);
    
        //used表示一共访问了几条边,ans是权值总和
        int used=0;
        int ans=0;
        //把所有的边取出,判断两个节点是否在一个集合里,如果是,则跳过,如果不在则加入集合并且让ans加上权,标记访问
        for (Edge edge : edges) {
            if (isSame(edge.u,edge.v)){
                continue;
            }
            join(edge.u,edge.v);
            ans+=edge.w;
            used++;
            //当找到n-1条边后,跳出循环,注意不要写成return
            if (used==n-1){
                break;
            }
        }
        
        //如果访问过的节点不是n-1,说明不成环无法连接
        if (used!=n-1){
            System.out.println("不成环");
        }
        else {
            System.out.println(ans);
        }
    }
}
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务