当前位置:   article > 正文

以图判树(并查集)_给定编号从0到n-1的n个节点,给定一个整数n和一个edges列表

给定编号从0到n-1的n个节点,给定一个整数n和一个edges列表

题目描述:

给定编号从 0 到 n - 1 的 n 个结点。给定一个整数 n 和一个 edges 列表,其中 edges[i] = [ai, bi] 表示图中节点 ai 和 bi 之间存在一条无向边。

如果这些边能够形成一个合法有效的树结构,则返回 true ,否则返回 false 。

实例:

输入: n = 5, edges = [[0,1],[0,2],[0,3],[1,4]]
输出: true

思路:

        对于小合集合并为大合集的题目首先就要想到并查集

        例如:已知两两亲戚关系,求A、B是否为亲属等问题。

        例如:已知结点边的集合,求是否构成单棵树。

并查集思路:

        1. 查找函数(find):

                对于某节点A,若A的前驱不等于本身,则让A=A.pre,并循环。

                直到找到一个节点,其前驱等于其本身。则此节点为先前A节点的根节点,返回该节点

        2. 合并函数(merge):

                对于A和B两个子树的根节点,判断其树高(or 树大小),小树合并到大树内。

                即:判断根节点A、B的size,若A.size<B.size,将A的前驱赋值为B。

        3.判断依据:

                若并查集之后,对于任意两个节点A、B,若A的根节点和B的根节点是同一个,则说明在同一个集合之中。

                对于上诉提到的亲戚案例,可以理解为:祖父相同,有血缘关系。

                对于以图判树题目,可以理解为:

                        ①若在合并过程中,处理新纪录时出现根节点一致的情况,说明有环,直接返回false

                        ②若在合并完成之后(说明已经无环),如果合并次数<节点数-1,说明无法构成一颗树,(即:有多个树存在),也需要返回false

                        ③若①、②都正常,则是一个正常的树,返回true。

        注意事项:

                对于用结构体树的写法,需要注意的是,find返回的并不是真正的很节点本身,而是根节点的拷贝。对于拷贝不能直接merge而是需要先找到真正的根节点再merge。

代码示例:        

  1. class Solution {
  2. private:
  3. int N;
  4. struct TreeNode{
  5. int data;
  6. int size;
  7. TreeNode * pre;
  8. };
  9. public:
  10. TreeNode find(TreeNode &node){
  11. TreeNode temp=node;
  12. while(temp.pre->data != temp.data){
  13. temp=*temp.pre;
  14. }
  15. //cout<<"temp"<<temp.data<<'\n';
  16. return temp;
  17. }
  18. int merge(TreeNode &node1,TreeNode &node2){
  19. if(node1.size>=node2.size){
  20. node1.pre = &node2;
  21. node2.size+=node1.size;
  22. }
  23. else{
  24. node2.pre = &node1;
  25. node1.size+=node2.size;
  26. }
  27. N--;
  28. return 0;
  29. }
  30. bool validTree(int n, vector<vector<int>>& edges) {
  31. N=n;
  32. TreeNode Node[n];
  33. for(int i=0;i<n;i++){
  34. Node[i].data=i;
  35. Node[i].pre = &Node[i];
  36. Node[i].size=1;
  37. }
  38. for(int i=0;i<edges.size();i++){
  39. TreeNode Node1 = find(Node[edges[i][0]]);
  40. TreeNode Node2 = find(Node[edges[i][1]]);
  41. cout<<"i="<<i<<' '<<Node1.data<<' '<<Node2.data<<'\n';
  42. if(Node1.data!=Node2.data){
  43. merge(Node[Node1.data],Node[Node2.data]);
  44. cout<<"merge="<<Node[Node1.data].pre->data<<' '<<Node[Node2.data].pre->data<<'\n';
  45. cout<<'\n';
  46. }
  47. else{
  48. cout<<"here1";
  49. return false;
  50. }
  51. }
  52. cout<<"here2="<<N;
  53. if(N==1) return true;
  54. else return false;
  55. }
  56. };

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

闽ICP备14008679号