Kruskal最小生成树算法

    1. 将所有的边按照权重非递减排序;
    2. 选择最小权重的边,判断是否其在当前的生成树中形成了一个环路。如果环路没有形成,则将该边加入树中,否则放弃。
    3. 重复步骤 2,直到有 V – 1 条边在生成树中。
  1. http://blog.jobbole.com/83939/
  2. using System;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace GraphAlgorithmTesting
    {
      class Program
      {
        static void Main(string[] args)
        {
          Graph g = new Graph(9);
          g.AddEdge(0, 1, 4);
          g.AddEdge(0, 7, 8);
          g.AddEdge(1, 2, 8);
          g.AddEdge(1, 7, 11);
          g.AddEdge(2, 3, 7);
          g.AddEdge(2, 5, 4);
          g.AddEdge(8, 2, 2);
          g.AddEdge(3, 4, 9);
          g.AddEdge(3, 5, 14);
          g.AddEdge(5, 4, 10);
          g.AddEdge(6, 5, 2);
          g.AddEdge(8, 6, 6);
          g.AddEdge(7, 6, 1);
          g.AddEdge(7, 8, 7);
    
          Console.WriteLine();
          Console.WriteLine("Graph Vertex Count : {0}", g.VertexCount);
          Console.WriteLine("Graph Edge Count : {0}", g.EdgeCount);
          Console.WriteLine();
    
          Console.WriteLine("Is there cycle in graph: {0}", g.HasCycle());
          Console.WriteLine();
    
          Edge[] mst = g.Kruskal();
          Console.WriteLine("MST Edges:");
          foreach (var edge in mst)
          {
            Console.WriteLine("\t{0}", edge);
          }
    
          Console.ReadKey();
        }
    
        class Edge
        {
          public Edge(int begin, int end, int weight)
          {
            this.Begin = begin;
            this.End = end;
            this.Weight = weight;
          }
    
          public int Begin { get; private set; }
          public int End { get; private set; }
          public int Weight { get; private set; }
    
          public override string ToString()
          {
            return string.Format(
              "Begin[{0}], End[{1}], Weight[{2}]",
              Begin, End, Weight);
          }
        }
    
        class Subset
        {
          public int Parent { get; set; }
          public int Rank { get; set; }
        }
    
        class Graph
        {
          private Dictionary<int, List<Edge>> _adjacentEdges
            = new Dictionary<int, List<Edge>>();
    
          public Graph(int vertexCount)
          {
            this.VertexCount = vertexCount;
          }
    
          public int VertexCount { get; private set; }
    
          public IEnumerable<int> Vertices { get { return _adjacentEdges.Keys; } }
    
          public IEnumerable<Edge> Edges
          {
            get { return _adjacentEdges.Values.SelectMany(e => e); }
          }
    
          public int EdgeCount { get { return this.Edges.Count(); } }
    
          public void AddEdge(int begin, int end, int weight)
          {
            if (!_adjacentEdges.ContainsKey(begin))
            {
              var edges = new List<Edge>();
              _adjacentEdges.Add(begin, edges);
            }
    
            _adjacentEdges[begin].Add(new Edge(begin, end, weight));
          }
    
          private int Find(Subset[] subsets, int i)
          {
            // find root and make root as parent of i (path compression)
            if (subsets[i].Parent != i)
              subsets[i].Parent = Find(subsets, subsets[i].Parent);
    
            return subsets[i].Parent;
          }
    
          private void Union(Subset[] subsets, int x, int y)
          {
            int xroot = Find(subsets, x);
            int yroot = Find(subsets, y);
    
            // Attach smaller rank tree under root of high rank tree
            // (Union by Rank)
            if (subsets[xroot].Rank < subsets[yroot].Rank)
              subsets[xroot].Parent = yroot;
            else if (subsets[xroot].Rank > subsets[yroot].Rank)
              subsets[yroot].Parent = xroot;
    
            // If ranks are same, then make one as root and increment
            // its rank by one
            else
            {
              subsets[yroot].Parent = xroot;
              subsets[xroot].Rank++;
            }
          }
    
          public bool HasCycle()
          {
            Subset[] subsets = new Subset[VertexCount];
            for (int i = 0; i < subsets.Length; i++)
            {
              subsets[i] = new Subset();
              subsets[i].Parent = i;
              subsets[i].Rank = 0;
            }
    
            // Iterate through all edges of graph, find subset of both
            // vertices of every edge, if both subsets are same,
            // then there is cycle in graph.
            foreach (var edge in this.Edges)
            {
              int x = Find(subsets, edge.Begin);
              int y = Find(subsets, edge.End);
    
              if (x == y)
              {
                return true;
              }
    
              Union(subsets, x, y);
            }
    
            return false;
          }
    
          public Edge[] Kruskal()
          {
            // This will store the resultant MST
            Edge[] mst = new Edge[VertexCount - 1];
    
            // Step 1: Sort all the edges in non-decreasing order of their weight
            // If we are not allowed to change the given graph, we can create a copy of
            // array of edges
            var sortedEdges = this.Edges.OrderBy(t => t.Weight);
            var enumerator = sortedEdges.GetEnumerator();
    
            // Allocate memory for creating V ssubsets
            // Create V subsets with single elements
            Subset[] subsets = new Subset[VertexCount];
            for (int i = 0; i < subsets.Length; i++)
            {
              subsets[i] = new Subset();
              subsets[i].Parent = i;
              subsets[i].Rank = 0;
            }
    
            // Number of edges to be taken is equal to V-1
            int e = 0;
            while (e < VertexCount - 1)
            {
              // Step 2: Pick the smallest edge. And increment the index
              // for next iteration
              Edge nextEdge;
              if (enumerator.MoveNext())
              {
                nextEdge = enumerator.Current;
    
                int x = Find(subsets, nextEdge.Begin);
                int y = Find(subsets, nextEdge.End);
    
                // If including this edge does‘t cause cycle, include it
                // in result and increment the index of result for next edge
                if (x != y)
                {
                  mst[e++] = nextEdge;
                  Union(subsets, x, y);
                }
                else
                {
                  // Else discard the nextEdge
                }
              }
            }
    
            return mst;
          }
        }
      }
    }
    

      

时间: 2024-10-03 22:42:44

Kruskal最小生成树算法的相关文章

[算法系列之二十七]Kruskal最小生成树算法

简介 求最小生成树一共有两种算法,一个是就是本文所说的Kruskal算法,另一个就是Prime算法.在详细讲解Kruskal最小生成树算法之前,让我们先回顾一下什么是最小生成树. 我们有一个带权值的图,我们要求找到一个所有生成树中具有最小权值的生成树.如下图所示,T是图G的生成树.但不是具有最小权值的生成树. 我们可以把他们想象成一组岛屿和连接它们的可能的桥梁.当然修桥是非常昂贵和费时的,所以我们必须要知道建设什么样的桥梁去连接各个岛.不过有一个重要的问题,建设这样一组连接所有岛屿的桥梁的最低价

Kruskal 最小生成树算法

对于一个给定的连通的无向图 G = (V, E),希望找到一个无回路的子集 T,T 是 E 的子集,它连接了所有的顶点,且其权值之和为最小. 因为 T 无回路且连接所有的顶点,所以它必然是一棵树,称为生成树(Spanning Tree),因为它生成了图 G.显然,由于树 T 连接了所有的顶点,所以树 T 有 V - 1 条边.一张图 G 可以有很多棵生成树,而把确定权值最小的树 T 的问题称为最小生成树问题(Minimum Spanning Tree).术语 "最小生成树" 实际上是

USACO 2007 December Contest, Silver Problem 2. Building Roads Kruskal最小生成树算法

PROBLEM: (ENGLISH VERSION) Farmer John had just acquired several new farms! He wants to connect the farms with roads so that he can travel from any farm to any other farm via a sequence of roads; roads already connect some of the farms. Each of the N

贪心算法(2)-Kruskal最小生成树

什么是最小生成树? 生成树是相对图来说的,一个图的生成树是一个树并把图的所有顶点连接在一起.一个图可以有许多不同的生成树.一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边.最小生成树其实是最小权重生成树的简称.生成树的权重是考虑到了生成树的每条边的权重的总和. 最小生成树有几条边? 最小生成树有(V – 1)条边,其中V是给定的图的顶点数量. Kruskal算法 下面是步骤寻找MST使用Kruskal算法 1 1,按照所有边的权重

最小生成树之克鲁斯卡尔(Kruskal)算法

学习最小生成树算法之前我们先来了解下 下面这些概念: 树(Tree):如果一个无向连通图中不存在回路,则这种图称为树. 生成树 (Spanning Tree):无向连通图G的一个子图如果是一颗包含G的所有顶点的树,则该子图称为G的生成树. 生成树是连通图的极小连通子图.这里所谓极小是指:若在树中任意增加一条边,则将出现一条回路:若去掉一条边,将会使之变成非连通图. 最小生成树(Minimum Spanning Tree,MST):或者称为最小代价树Minimum-cost Spanning Tr

无向带权图的最小生成树算法——Prim及Kruskal算法思路

边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权. 最小生成树(MST):权值最小的生成树. 生成树和最小生成树的应用:要连通n个城市需要n-1条边线路.可以把边上的权值解释为线路的造价.则最小生成树表示使其造价最小的生成树. 构造网的最小生成树必须解决下面两个问题: 1.尽可能选取权值小的边,但不能构成回路: 2.选取n-1条恰当的边以连通n个顶点: MST性质:假设G=(V,E)是一个连通网,U是顶点V的一个非空子集.若(u,v)是一条具有最小权值的

最小生成树(MST)----普里姆(Prim)算法与克鲁斯卡尔(Kruskal)算法

1.概念:给定一个带权的无向连通图,如何选取一棵生成树,使树上所有边上权的总和为最小,这叫最小生成树. 2.应用:例如:要在n个城市之间铺设光缆,主要目标是要使这 n 个城市的任意两个之间都可以通信,但铺设光缆的费用很高,且各个城市之间铺设光缆的费用不同,因此另一个目标是要使铺设光缆的总费用最低.这就需要找到带权的最小生成树. 3.求最小生成树的算法 3.1 普里姆(Prim)算法 方法:从指定顶点开始将它加入集合中,然后将集合内的顶点与集合外的顶点所构成的所有边中选取权值最小的一条边作为生成树

[算法第一轮复习] kruskal求最小生成树算法

最小生成树算法即MST,有kruskal,prim两种算法,这里主要介绍kruskal 什么是最小生成树? 对于一个图,保证其中每个点都可以连通的最小的花费 1.算法核心 贪心+并查集 2.算法实现过程 克鲁斯卡尔算法 假设 WN=(V,{E}) 是一个含有 n 个顶点的连通网,则按照克鲁斯卡尔算法构造最小生成树的过程为:先构造一个只含 n 个顶点,而边集为空的子图,若将该子图中各个顶点看成是各棵树上的根结点,则它是一个含有 n 棵树的一个森林.之后,从网的边集 E 中选取一条权值最小的边,若该

c/c++ 用克鲁斯卡尔(kruskal)算法构造最小生成树

c/c++ 用克鲁斯卡尔(kruskal)算法构造最小生成树 最小生成树(Minimum Cost Spanning Tree)的概念: 假设要在n个城市之间建立公路,则连通n个城市只需要n-1条线路.这时,自然会考虑,如何在最节省经费的前提下建立这个公路网络. 每2个城市之间都可以设置一条公路,相应地都要付出一定的经济代价.n个城市之间,最多可以设置n(n-1)/2条线路,那么,如何在这些可能的线路中选择n-1条,以使总的耗费最少? 克鲁斯卡尔(kruskal)算法的大致思路: 把每条边的权重