堆+并查集 实现 kruskal算法

堆+并查集 实现 kruskal算法

废话少说,下面是大家都熟悉的kruskal算法,重点在于实现,时间复杂度为O(e*loge),其中e为边数。

  1  //  这个算法用kruskal实现了
  2  #include  < iostream >
  3  #include  < algorithm >
  4 
  5  using namespace std;
  6 
  7  const   int  maxn = 100 ;
  8 
  9  int  m[maxn];
 10  //  边的结构体
 11  struct node{
 12       int  u,v;
 13       double  cost;
 14      bool operator  < (node a)
 15      {
 16           return  cost > a.cost;
 17      }
 18  }e[maxn];
 19 
 20 
 21 
 22  //  边数
 23  int  ce;
 24  //  点数
 25  int  n;
 26  int  heap[maxn];
 27  //  堆大小
 28  int  hsize;
 29 
 30  void  merge( int  i, int  j)
 31  {
 32       //  i所代表的集合中元素数小于j所代表的
 33       if (m[i] > m[j]){
 34          m[j] += m[i];
 35          m[i] = j;
 36      } else {
 37          m[i] += m[j];
 38          m[j] = i;
 39      }
 40  }
 41 
 42  int  find( int  i)
 43  {
 44       int  j,k,t;
 45       //  从i回溯到根
 46       for (j = i;m[j] > 0 ;j = m[j]);
 47       //  路径压缩,将从i到j路径上所有点的父亲设为j
 48       for (k = i;k != j;k = t){
 49          t = m[k];
 50          m[k] = j;
 51      }
 52       return  j;
 53  }
 54 
 55  void  init()
 56  {
 57      memset(m, - 1 ,sizeof(m));
 58       return ;
 59  }
 60 
 61  void  siftdown( int  index)
 62  {
 63      heap[index] = heap[hsize];
 64      hsize -- ;
 65       int  i = index,j,tmp;
 66       while ( 2 * i <= hsize){
 67          j = 2 * i;
 68           if (j + 1 <= hsize  &&  e[heap[j + 1 ]].cost > e[heap[j]].cost) j ++ ;
 69           if (e[heap[i]].cost > e[heap[j]].cost)  break ;
 70          tmp = heap[i];
 71          heap[i] = heap[j];
 72          heap[j] = tmp;
 73          i = j;
 74      }
 75  }
 76 
 77  int  extract()
 78  {
 79       int  res = heap[ 1 ];
 80      siftdown( 1 );
 81       return  res;
 82  }
 83 
 84  void  siftup( int  index)
 85  {
 86       int  i = index,tmp;
 87       while (i > 1   &&  e[heap[i / 2 ]].cost < e[heap[i]].cost){
 88          tmp = heap[i / 2 ];
 89          heap[i / 2 ] = heap[i];
 90          heap[i] = tmp;
 91          i /= 2 ;
 92      }
 93  }
 94 
 95 
 96  //  用kruskal求最大生成树
 97  void  kruskal()
 98  {
 99       //  初始化并查集
100      init();
101       int  i;
102       //  初始化堆
103       // sort(e+1,e+ce+1);
104       for (i = 1 ;i <= ce;i ++ ){
105          heap[i] = i;
106          siftup(i);
107      }
108      hsize = ce;
109       //  算法开始
110       double  total = 0.0 ;
111       int  mergeTime = 0 ;     //  只需合并n-1次
112       int  a,b;
113       while (hsize > 0   &&  mergeTime < n - 1 ){
114          i = extract();
115          a = find(e[i].u);
116          b = find(e[i].v);
117           //  若a,b处在不同的集合中
118           if (a != b){
119              merge(a,b);
120              total += e[i].cost;
121              printf( " merge edge(%d,%d) with cost %.2lf\n " ,e[i].u,e[i].v,e[i].cost);
122          }
123      }
124      printf( " total cost %.2lf\n: " ,total);
125       return ;
126  }
127 
128  int  main()
129  {
130      freopen( " graph.txt " , " r " ,stdin);
131      scanf( " %d%d " , & n, & ce);
132       int  i,j,k,c;
133       for (i = 1 ;i <= ce;i ++ ) scanf( " %d%d%lf " , & e[i].u, & e[i].v, & e[i].cost);
134      kruskal();
135       return   1 ;
136  }

你可能感兴趣的:(堆+并查集 实现 kruskal算法)