【蓝桥杯集训17】最小生成树 Prim Kruskal(2 / 3)

目录

最小生成树概念 

Prim求最小生成树

Kruskal求最小生成树


最小生成树概念 

给定一个无向图,在图中选择若干条边把图的所有节点连起来

要求边长之和最小,在图论中,叫做求最小生成树

Prim求最小生成树

初始化准备:

dist[i]=i点到生成树集合的最短距离   初始化dist[i]=0x3f3f3f3f   dist[1]=0

稠密图g[][]初始化0x3f3f3f3f

n次循环

{

        1、从1~n点中找到未标记的点中,离生成树集合最近的点

        2、如果是孤立点且不是第一个节点(dist[t]==0x3f3f3f3f)则不可能生成最小生成树

        3、标记该点

        4、(如果不是第一个节点)记录最小生成树边权之和

        5、用该点更新其他点到集合的最小距离

}

public static int prim()
    {
        Arrays.fill(dist,0x3f3f3f3f);
        dist[1]=0;
        int res=0;
        
        for(int i=0;i<n;i++)
        {
            int t=-1;
            for(int j=1;j<=n;j++) //找到离集合最近的点
                if(st[j]==0&&(t==-1||dist[j]<dist[t])) t=j;
                
            if(i!=0&&dist[t]==0x3f3f3f3f) return 0x3f3f3f3f;
                
            st[t]=1;
            if(i!=0) res+=dist[t];
            
            for(int j=1;j<=n;j++) //用该点更新其他点到集合的最小距离
                dist[j]=Math.min(dist[j],g[t][j]);
                    
        }
        return res;
    }

联系:Dijkstra算法是更新到起始点的距离,Prim是更新到集合S的距离

/*
    *道阻且长,行则将至*
    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];
    static int[] pre=new int[N];
    
    public static int prim()
    {
        Arrays.fill(dist,0x3f3f3f3f);
        dist[1]=0;
        int res=0;
        
        for(int i=0;i<n;i++)
        {
            int t=-1;
            for(int j=1;j<=n;j++) //找到离集合最近的点
                if(st[j]==0&&(t==-1||dist[j]<dist[t])) t=j;
                
            if(i!=0&&dist[t]==0x3f3f3f3f) return 0x3f3f3f3f;
                
            st[t]=1;
            if(i!=0) res+=dist[t];
            
            for(int j=1;j<=n;j++) //用该点更新其他点到集合的最小距离
                if(dist[j]>g[t][j])
                {
                    dist[j]=g[t][j];
                    pre[j]=t; //则j的前驱节点就是t
                }
        }
        return res;
    }
    
    public static void getPath()
    {
        for(int i=n;i>1;i--)
            wt.println(i+" "+pre[i]+" ");
    }
    
    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]=g[b][a]=Math.min(g[a][b],c);
        }
        int t=prim();
        if(t==0x3f3f3f3f) wt.println("impossible");
        else wt.println(t);
        //getPath();
        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);
    }
}

Kruskal求最小生成树

  • 将所有边权值按从小到大排序
  • 遍历每两条边a b,如果ab不连通,则将ab放入集合中,记录cnt边数
  • 如果cnt<n-1(n个点n-1条边)则说明不能生成最小生成树
/*
    *道阻且长,行则将至*
    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=101000,M=2*N;
    static int n,m;
    static int[] p=new int[N];
    static Node[] node=new Node[M];
    
    public static int find(int x)
    {
        if(x!=p[x]) p[x]=find(p[x]);
        return p[x];
    }
    
    public static void main(String[] args) throws IOException
    {
        n=rd.nextInt();
        m=rd.nextInt();
        
        
        for(int i=1;i<=n;i++) p[i]=i;
        
        for(int i=0;i<m;i++)
        {
            int a=rd.nextInt(),b=rd.nextInt(),c=rd.nextInt();
            node[i]=new Node(a,b,c);
        }
        
        //按边权值从小到大排序
        Arrays.sort(node,0,m,(o1,o2)->o1.c-o2.c);
        
        //循环每一条边
        int cnt=0,res=0;
        for(int i=0;i<m;i++)
        {
            int a=find(node[i].a),b=find(node[i].b);
            if(a!=b)
            {
                p[a]=b;
                cnt++;
                res+=node[i].c;
            }
        }
        if(cnt<n-1) wt.print("impossible"); //n个点n-1条边
        else wt.print(res);
        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 Node
{
    int a,b,c;
    public Node(int aa,int bb,int cc)
    {
        a=aa;
        b=bb;
        c=cc;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值