当前位置:   article > 正文

并查集(Disjoint Set)_并查集求奇环

并查集求奇环

七、并查集(Disjoint Set)

1、引入

并查集是用于检查图中是否存在环状结构的。

列:

 

通过并查集检测上诉图中是否有环

(1)、先将六个顶点平铺开来

(2)、 将两边相连的顶点放入一个结合中

此时的集合将有两个性质: ​

①集合中的每一个顶点都可以通向另一个顶点

②如果从此集合中任选两个顶点就会构成一个环

(3)、用一维数组构成树

①0的父节点是1:parent[0]=1;

②2的父节点是1:parent[2]=1;

得到:

 

 

③3的父节点是4:parent[3]=4;

得到:

(4)、合并父节点

(5)、寻找其中两个顶点的根

如果两个顶点的根相同,则可得到一个环。

2、实现

  1. #define Vertices 6
  2. //初始化数组
  3. void initialise(int parent[])
  4. {
  5. int i;
  6. for(i=0;i<Vertices;i++)
  7. {
  8. parent[i]=-1;
  9. }
  10. }
  11. //寻找根节点
  12. int find_root(int x,int parent[])
  13. {
  14. //先假设一个根结点x_root
  15. int x_root=x;
  16. //如果parent[x_root]为-1代表找到根结点
  17. while(parent[x_root]!=-1)
  18. {
  19. //不然就找向上一个顶点
  20. x_root=parent[x_root];
  21. }
  22. return x_root;
  23. }
  24. //合并两个树
  25. //如果return 1则合并成功,如果return 0则合并失败
  26. int union_vertices(int x,int y,int parent[])
  27. {
  28. //寻找x和y两棵树的根结点
  29. int x_root=find_root(x,parent);
  30. int y_root=find_root(x,parent);
  31. //如果两棵树的根结点相同则合并失败
  32. if(x_root==y_root)
  33. {
  34. return 0;
  35. }
  36. else
  37. {
  38. //把x的根结点连接向y的根节点
  39. parent[x_root]=y_root;
  40. return 1;
  41. }
  42. }
  43. int mian()
  44. {
  45. int parent[Vertices]={0};
  46. initialise(parent);
  47. int edges[6][2]={
  48. {0,1},{1,2},{1,3},
  49. {2,4},{3,4},{2,5}
  50. }
  51. int i=0;
  52. for(i=0;i<6;i++)
  53. {
  54. int x=edges[i][0];
  55. int y=edges[i][1];
  56. if(union_vertices(x,y,parent)==0)
  57. {
  58. printf("图中有环\n");
  59. exit(0);
  60. }
  61. }
  62. printf("图中没有环!\n");
  63. return 0;
  64. }

方便大家对照的: 

 压缩路径

  1. //未压缩
  2. int find(int x)
  3. {
  4. if (x==parent[x])return x;
  5. return find(parent[x]);
  6. }
  7. //压缩后
  8. int find(int x)
  9. {
  10. if(x==parent[x]) return x;
  11. //每次都将对应的根存储在对应的叶上
  12. else parent[x]=find(parent[x]);
  13. return parent[x];
  14. }

秩序合并

  1. void union(int lx,int ly)//传入x、y
  2. {
  3. x_root=find(x); //寻找 x的代表元
  4. y_root=find(y); //寻找 y的代表元
  5. if(x_root==y_root) return ; //如果 x和 y的代表元一致,说明他们共属同一集合,则不需要合并,直接返回;否则,执行下面的逻辑
  6. if(rank[x]>rank[y]) pre[y]=x; //如果 x的高度大于 y,则令 y的上级为 x
  7. else //否则
  8. {
  9. if(rank[x]==rank[y]) rank[y]++; //如果 x的高度和 y的高度相同,则令 y的高度加1
  10. pre[x]=y; //让 x的上级为 y
  11. }
  12. }

 时间匆匆,唯有记录才可留下。欢迎斧正、交流。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/836026
推荐阅读
相关标签
  

闽ICP备14008679号