zoukankan      html  css  js  c++  java
  • 并查集,最小生成树

    并查集

      字面意思就是几个集合的并集,和这个并集的查找。

      百度百科:并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,

      然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。

      在博客上,看到一篇很生动的文章,关于并查集的。看了它,也就基本知道并查集的求法了https://blog.csdn.net/u013546077/article/details/64509038

    最小生成树:

      一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。

      最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出。 [2

      Prim算法:

      1).输入:一个加权连通图,其中顶点集合为V,边集合为E;
      2).初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;
      3).重复下列操作,直到Vnew = V:
      a.在集合E中选取权值最小的边<u, v>,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
      b.将v加入集合Vnew中,将<u, v>边加入集合Enew中;
      4).输出:使用集合Vnew和Enew来描述所得到的最小生成树
      HDU - 1233
      我做这道题目的时候,虽然明白了prim算法,但是不知道增加最小的边,后来用了一个时间复杂度O(N3)的算法,就是在添加新边的时候,从已有的点从头到尾遍历,结果超时了。
      后来知道可以用贪心的思想,很快就写出来了。
      代码实现如何:
    import java.util.Arrays;
    import java.util.Scanner;
    
    public class Main
    {
        static final int MAX = 105;
        static final int INF = 1000005;
        static int dis[][] = new int[MAX][MAX];
        static int mid[] = new int[MAX];
        static boolean vis[] = new boolean[MAX];
        public static void main(String []args)
        {
            Scanner cin = new Scanner(System.in);
            while(true)
            {
                int N = cin.nextInt();
                if(N == 0)
                {
                    return;
                }
                else if(N == 1)
                {
                    System.out.println(0);
                    continue;
                }
                Arrays.fill(vis, false);
                int M = N*(N-1)/2;
                for(int i = 0; i < M; i++)
                {
                    int a,b,c;
                    a = cin.nextInt();
                    b = cin.nextInt();
                    c = cin.nextInt();
                    dis[a][b] = c;
                    dis[b][a] = c;
                }
                System.out.println(Prim(N));
            }
        }
        static int Prim(int N)
        {
            int sum = 0;
            mid[1] = 0;
            for(int i = 2; i <= N; i++)
            {
                mid[i] = dis[1][i];
                if(dis[1][i] == 0)
                {
                    mid[i] = INF;
                }
            }
            vis[1] = true;
            for(int i = 2; i <= N; i++)
            {
                int Min = INF;
                int temp = 0;
                for(int j = 2; j <= N; j++)
                {
                    if(vis[j] == false && Min > mid[j])
                    {
                        Min = mid[j];
                        temp = j;
                    }
                }
                vis[temp] = true;
                sum += Min;
                for(int j = 2; j <= N; j++)
                {
                    if(vis[j] == false && mid[temp]+dis[temp][j] < mid[j])
                    {
                        mid[j] = mid[temp]+dis[temp][j];
                    }
                }
            }
        }
    }

      kruskal算法的实现过程,有自己去实践了!

     
     

      

  • 相关阅读:
    Controlling behavior of existing services in system
    获取站点路径方法
    如何处理DataTable.Select();执行后重新排序的问题!
    ASP.NET 2.0 编程珠玑之五调试已创建好的代码
    Meal Scheduler in C#
    DHTML+Ajax? MXML+ActionScript? XAML+C#? 是巧合,还是必然?
    C#验证输入的是否数字
    Monitoring System Usage using Windows Service
    ADO.NET 2.0中的DataSet和DataTable
    使用asp.net 2.0和SQL SERVER 2005构建多层应用
  • 原文地址:https://www.cnblogs.com/674001396long/p/9984808.html
Copyright © 2011-2022 走看看