最小生成树【kruskal、prim】

例题: AcWing 859、kruskal

1、kruskal

思想:将边从小到大排序,每次判断这条边的两个节点是否已经联通,如果没有联通的话就把这条边加入。

import java.util.*;

public class Main{
    static int par[];
    static int find(int x){
        int root=x;
        //找到x的祖父节点【最上面的节点】
        while(root!=par[root]) root=par[root];
        while(root!=x){
            //修改x上面的节点,将他们的祖父节点指向root
            int t=par[x];
            par[x]=root;
            x=t;
        }
        return root;
    }
    static void union(int x,int y){
        x=find(x);
        y=find(y);
        if(x!=y){
            par[x]=y;
        }
    }
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt(),m=sc.nextInt();
        par=new int[n];
        for(int i=0;i<n;i++)
            par[i]=i;
        int[][] edges=new int[m][3];
        for(int i=0;i<m;i++){
            edges[i][0]=sc.nextInt()-1;
            edges[i][1]=sc.nextInt()-1;
            edges[i][2]=sc.nextInt();
        }
        Arrays.sort(edges,(o1,o2)->o1[2]-o2[2]);
        int ans=0,nEdge=0;
        for(int[] edge:edges){
            int from=edge[0],to=edge[1],val=edge[2];
            if(find(from)!=find(to)){
                union(from,to);
                ans+=val;
                nEdge++;
            }
        }
        if(nEdge<n-1){
            System.out.println("impossible");
        }else{
            System.out.println(ans);
        }
    }

}


2、prim

思想:跟dijkstra差不多,根据当前已经更新的节点去延伸,将边加入到集合中

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt(),m=sc.nextInt();
        int[] dist=new int[n];
        int[][] g=new int[n][n];
        int ans=0,max=Integer.MAX_VALUE/2;
        boolean[] vis=new boolean[n];
        Arrays.fill(dist,max);
        for(int i=0;i<n;i++)
            Arrays.fill(g[i],max);
        for(int i=0;i<m;i++){
            int a=sc.nextInt()-1;
            int b=sc.nextInt()-1;
            int c=sc.nextInt();
            g[a][b]=Math.min(g[a][b],c);
            g[b][a]=g[a][b];
        }
        dist[0]=0;
        for(int i=0;i<n;i++){
            int t=-1,min=max;
            for(int j=0;j<n;j++){
                if(!vis[j]&&dist[j]<min){
                    t=j;
                    min=dist[j];
                }
            }
            //没有其它联通的点了
            if(t==-1){
                System.out.println("impossible");
                return ;
            }
            ans+=dist[t];
            vis[t]=true;
            for(int j=0;j<n;j++){
                if(!vis[j]&&g[t][j]<dist[j]){
                    dist[j]=g[t][j];
                }
            }
        }
        System.out.println(ans);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值