POJ 1988 Cube Stacking (并查集,节点到根节点的距离题目)

首先看到这个题号的时候我想起了好公民,韩寒同学和他的不死鸟= =

本人二蛋一枚,近日做了些并查集的东西但是一直不太明白怎么才能查节点路径,而且觉得要是迭代的时候加了r[x]的话会出现多加的情况,后来经网上高人指点(觉得还是好人多,虽然自己确实不想做好人了= =)明白了~

一下是高人话语~

void merge(int a,int b)
{
father[a]=b;
place[a]+=number[b];
number[b]+=number[a];
}

int Find(int a)//检查找和路径压缩
{
if(father[a]==-1)return a;
int tmp=father[a];
father[a]=Find(father[a]);
place[a]+=place[tmp];//你需要主要思考这一句话!
return father[a];
}

上面的代码是这一道题目的精华,标红字的需要你仔细体会,它确实使我想了好几天才明白。首先,在读了Union代码之后你会发现:当我们把一棵树接在另一棵树的上面时,只有根节点的place值变化了。在思考后,你将会惊讶地发现,其实每个点的place值都是与它父亲place值的相对值!当它的父亲路径压缩后直接接在“顶头上司”之下时,也就是说,当它的父亲完成路径压缩的递归时,它的place值将会是它原来与它父亲的相对值加上现在父亲与“顶头上司”的相对值,想明白这一点,你就无敌了!最后请注意:执行C命令时,输出place[a]之前不要忘了路径压缩哦,至于为什么,原理你明白……

这样的话给出我的代码

View Code
 1 #include <iostream>
 2 #include <stdio.h>
 3 using namespace std;
 4 int set[30005],r[30005],num[30005];
 5 int find(int x)
 6 {
 7     int temp;
 8     temp = set[x];
 9     if(x != set[x])
10     {
11         set[x] = find(set[x]);
12         r[x] += r[temp];
13     }
14 
15     return set[x];
16 }
17 void merge(int x,int y)
18 {
19     x = find(x);
20     y = find(y);
21     if(x != y)
22     {
23         set[x] = y;
24         r[x] += num[y];
25         num[y] += num[x];
26     }
27 
28 }
29 int main()
30 {
31     int t,i,x,y;
32     char order[5];
33     scanf("%d",&t);
34     for(i = 1;i < 30005;i++)
35     set[i] = i,r[i] = 0,num[i] = 1;
36     while(t--)
37     {
38         scanf("%s %d",order,&x);
39         if(order[0] == 'M')
40         {
41             scanf("%d",&y);
42             merge(x,y);
43         }
44         else
45         {
46             find(x);
47             printf("%d\n",r[x]);
48         }
49 
50     }
51     return 0;
52 }

 

 

posted @ 2012-07-26 10:26  某某。  阅读(287)  评论(0编辑  收藏  举报