C++怎么实现基于不相交集合的kruskal算法

其他教程   发布日期:2023年06月28日   浏览次数:507

这篇文章主要介绍“C++怎么实现基于不相交集合的kruskal算法”,在日常操作中,相信很多人在C++怎么实现基于不相交集合的kruskal算法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++怎么实现基于不相交集合的kruskal算法”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

    C++实现基于不相交集合的O(mlgn)复杂度的kruskal算法

    不相交集合的数据结构

    我们采用森林的方式实现不相交集合。这个森林是极简化的,每个节点只有一个指向父亲的指针,而且森林中的每一颗树都是一个集合,我们取树的根节点为这个集合的代表元。

    1. int rank[505];
    2. int father[505];
    3. void make_set(int x)
    4. {
    5. father[x]=x;
    6. rank[x]=0;
    7. }
    8. int find_set(int x)
    9. {
    10. if (x!=father[x])
    11. {
    12. father[x]=find_set(father[x]);
    13. }
    14. return father[x];
    15. }
    16. void simply_union_set(int u,int v)
    17. {
    18. u=find_set(u);
    19. v=find_set(v);
    20. father[u]=v;
    21. }
    22. void perfect_union_set(int u,int v)
    23. {
    24. u=find_set(u);
    25. v=find_set(v);
    26. if (rank[u]>rank[v])
    27. {
    28. father[v]=u;
    29. }
    30. else
    31. {
    32. father[u]=v;
    33. if(rank[u]==rank[v])
    34. rank[v]++;
    35. }
    36. }

    可以看到在find_set()函数中采用了两趟遍历的思想,第一趟遍历找的根节点,第二趟遍历将路径上的节点全部指向根节点,完成了压缩树高。

    在实现集合合并的时候,我们采用了两种方法:一种方法是直接合并simply_union_set,另一种是采用按秩合并的思想perfect_union_set,即总是让秩小合并到秩大的集合中,这是一种减少树高的有效策略;

    当我们采用按秩合并时时,上述每一个操作的最差时间复杂度,都约等于O(1)

    kruskal 算法

    1. void kruskal()
    2. {
    3. for(int i=0;i<num_v;i++)make_set(i);
    4. sort(arr_edge.begin(),arr_edge.end(),mycompare);
    5. for(int i=0;i<arr_edge.size();i++)
    6. {
    7. int fr=arr_edge[i].fr;
    8. int to=arr_edge[i].to;
    9. int w=arr_edge[i].w;
    10. if( find_set(fr)!=find_set(to))
    11. {
    12. result+=w;
    13. perfect_union_set(fr,to);
    14. }
    15. }
    16. }

    kruskal 算法是一种基于贪心策略的算法,它的时间复杂度的最大开销就是排序算法,即O(mlgm)=O(mlgn),这里m表示边数,n表示顶点数

    知识补充

    乘胜追击一下,通过一个例题再深入了解一下kruskal 算法吧

    思路:就是最小生成树啊

    代码

    1. #include<iostream>
    2. #include<algorithm>
    3. #include<cstring>
    4. #include<cstdio>
    5. #include<vector>
    6. using namespace std;
    7. #define INTMAX 0x3f3f3f3f
    8. typedef pair<int,int> pii;
    9. typedef long long ll;
    10. #define x first
    11. #define y second
    12. int rank[505];
    13. int father[505];
    14. int find_set(int x)
    15. {
    16. if (x!=father[x])
    17. {
    18. father[x]=find_set(father[x]);
    19. }
    20. return father[x];
    21. }
    22. void simply_union_set(int u,int v)
    23. {
    24. u=find_set(u);
    25. v=find_set(v);
    26. father[u]=v;
    27. }
    28. void perfect_union_set(int u,int v)
    29. {
    30. u=find_set(u);
    31. v=find_set(v);
    32. if (rank[u]>rank[v])
    33. {
    34. father[v]=u;
    35. }
    36. else
    37. {
    38. father[u]=v;
    39. if(rank[u]==rank[v])
    40. rank[v]++;
    41. }
    42. }
    43. struct edge
    44. {
    45. int fr,to,w;
    46. };
    47. int num_case,num_v,result;
    48. vector<edge> arr_edge;
    49. void debug()
    50. {
    51. for(int i=0;i<arr_edge.size();i++)
    52. {
    53. cout<<arr_edge[i].fr<<" to "<<arr_edge[i].to<<"="<<arr_edge[i].w<<endl;
    54. }
    55. }
    56. void init()
    57. {
    58. arr_edge.clear();
    59. result=0;
    60. }
    61. void input()
    62. {
    63. int w;
    64. scanf("%d",&num_v);
    65. for(int i=0;i<num_v;i++)
    66. {
    67. for(int j=0;j<num_v;j++)
    68. {
    69. scanf("%d",&w);
    70. if(i<j)
    71. {
    72. edge temp;
    73. temp.fr=i;
    74. temp.to=j;
    75. temp.w=w;
    76. arr_edge.push_back(temp);
    77. }
    78. }
    79. }
    80. }
    81. bool mycompare(const edge& x,const edge &y)
    82. {
    83. return x.w<y.w;
    84. }
    85. void kruskal()
    86. {
    87. for(int i=0;i<num_v;i++)father[i]=i;
    88. sort(arr_edge.begin(),arr_edge.end(),mycompare);
    89. for(int i=0;i<arr_edge.size();i++)
    90. {
    91. int fr=arr_edge[i].fr;
    92. int to=arr_edge[i].to;
    93. int w=arr_edge[i].w;
    94. if( find_set(fr)!=find_set(to))
    95. {
    96. result=max(result,w);
    97. simply_union_set(fr,to);
    98. }
    99. }
    100. }
    101. void solve()
    102. {
    103. init();
    104. input();
    105. //debug();
    106. kruskal();
    107. cout<<result<<endl;
    108. }
    109. int main()
    110. {
    111. scanf("%d",&num_case);
    112. while(num_case--)
    113. {
    114. solve();
    115. }
    116. return 0;
    117. }

    以上就是C++怎么实现基于不相交集合的kruskal算法的详细内容,更多关于C++怎么实现基于不相交集合的kruskal算法的资料请关注九品源码其它相关文章!