Dragon Balls

通过这道题,对并查集的查找又有了一定的认识,初步理解了路径压缩的好处,这里,根结点的转移次数不是直接加上根结点的移动次数,而是在路径压缩的过程中逐层累加,比如有4层,根结点为1,然后第二层2,第三层3,第四层4.那么,第一层路径压缩过程中进入第二层,然后第三层,然后第四层,第四层也就是根,找到根结点,返回第三层,第三层+上第四层的转移次数,然后返回第二层,第二层转移次数加上第三层转移次数,返回第一层,第一层转移次数加上第二层转移次数,同时,在这个过程中也把下面3层的结点的父节点直接更新为和根结点,也就是1相连,查找结束后,称为2层结构,根结点1在一层,234都处于第二层。这样的一个过程是通过递归调用本身完成的,跟数据结构(严蔚敏版本)讲解栈那节的汉诺塔过程相似,如果想完全掌握,推荐仔细看教材+自己模拟,这样就可以理解了。。。。。


代码如下:

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cstdio>  
  3. #include<cstring>  
  4. #include<algorithm>  
  5. using namespace std;  
  6. #define N 10010  
  7.   
  8. struct node  
  9. {  
  10.     int parent; //根节点  
  11.     int son; //子节点  
  12.     int transport; //转移次数  
  13. }p[N];  
  14.   
  15. int find(int x)  
  16. {  
  17.     int temp;  
  18.     if(x == p[x].parent)  
  19.         return x;  
  20.     else  
  21.     {  
  22.         temp = p[x].parent;  
  23.         p[x].parent = find(p[x].parent);  
  24.         p[x].transport += p[temp].transport; //这点需要反复揣摩  
  25.     }  
  26.     return p[x].parent;  
  27. }  
  28.   
  29. void join(int x, int y)  
  30. {  
  31.     int root1, root2;  
  32.     root1 = find(x);  
  33.     root2 = find(y);  
  34.     if(root1 == root2)  
  35.         return ;  
  36.     p[root1].parent = root2;  
  37.     p[root1].transport++; //根节点转移次数+1,要理解  
  38.     p[root2].son += p[root1].son;  
  39.     p[root1].son = 0;  
  40. }  
  41.   
  42. int main()  
  43. {  
  44.     int ncase, T = 1;  
  45.     int num, querynum;  
  46.     char ope;  
  47.     int from, to;  
  48.     int querycity;  
  49.     int ans;  
  50.     scanf("%d", &ncase);  
  51.     while(ncase--)  
  52.     {  
  53.         scanf("%d%d", &num, &querynum);  
  54.         for(int i = 1; i <= num; ++i) //初始化  
  55.         {  
  56.             p[i].parent = i;  
  57.             p[i].son = 1;  
  58.             p[i].transport = 0;  
  59.         }  
  60.         printf("Case %d:\n", T++);  
  61.         for(int i = 0; i < querynum; ++i)  
  62.         {  
  63.             scanf("%*c%c", &ope);  
  64.             if(ope == 'T')  
  65.             {  
  66.                 scanf("%d%d", &from, &to);  
  67.                 join(from, to);  
  68.             }  
  69.             else  
  70.             {  
  71.                 scanf("%d", &querycity);  
  72.                 ans = find(querycity);  
  73.                 printf("%d %d %d\n", ans, p[ans].son, p[querycity].transport); //纠结了3个小时~~  
  74.             }  
  75.         }  
  76.     }  
  77.     return 0;  
  78. }          
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值