The Way of C++

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  55 Posts :: 0 Stories :: 19 Comments :: 0 Trackbacks

公告

The first time i use this blog, i will write something that i learn which i think is worth write down.

常用链接

留言簿(3)

我参与的团队

搜索

  •  

最新评论

阅读排行榜

评论排行榜

  题意是给出N个立方体,可以将立方体移动到其它立方体形成堆,然后有P个下面的操作: 1) M X Y ,将X立方体所在的堆移到Y立方体所在的堆的上面;  2) C X 输出在X所在的堆上,在X立方体下面的立方体个数。
  使用并查集来解决这个问题。关键在于怎么存储和更新立方体的结果(即操作2的输出值)。用三个数组,p,h,t, p[i]表示i的根结点,h[i]表示i的结果,即压在i下面的立方体个数,t[i]表示i所在的堆的立方体总个数。对于每一堆立方体,根结点使用堆底的立方体,而且在这个堆所对应的集合内,通过更新,使得只有根结点的t值为这堆的总个数,h值为0(因为它在堆底),其它的立方体的t值都为0,h值在并查集的查找步骤中进行递归更新。   
  在并查集的查找函数的执行中,先向上找到根结点,并且保存当前结点x的父节点为temp,找到根结点后,向下依次一更新结点的h,t值。
      1)若t[x]不为0,即表示x是一个堆的堆底元素,h[x]为0,其父节点是另外一堆的堆底(因为在并查集的操作中,通过将一个堆的堆底指向另一个堆的堆底来实现合并), h[x]+=t[temp],t[temp]+=t[x],t[x]=0 ,这三个语句将x的h值加上父结点的总个数(因为是将x所在的堆放在父节点的堆),然后将父节点的t值加上x的t值(父节点的堆的总数变为两者之和),然后再将x的t值置0.
      2)若t[x]为0,即表示x不是堆底,那么只要将x的h值加上父节点的h值即可。h[x]+=h[temp] 。
  画个图然后稍微分析查找操作的过程就能得到上面的结果。下面是并查集的几个函数。在合并操作里面,合并完后我们再对x,y执行一次查找操作以更新对应堆的值,因为在下次合并的时候可能堆还没有来得及更新。
 1 void make_set()
 2 {
 3     int i;
 4     for(i=1;i<N;++i)
 5     {
 6         p[i]=i;
 7         h[i]=0;
 8         t[i]=1;
 9     }
10 }
11 int find_set(int x)
12 {
13     int temp;
14     if(x!=p[x])
15     {
16         temp=p[x];
17         p[x]=find_set(p[x]);
18         if(t[x]!=0)
19         {
20             h[x]+=t[temp];
21             t[temp]+=t[x];
22             t[x]=0;
23         }else
24         {
25             h[x]+=h[temp];
26         }
27     }
28     return p[x];
29 }
30 void union_set(int x,int y)
31 {
32     int px=find_set(x),py=find_set(y);
33     p[px]=py;
34     find_set(x),find_set(y);
35 }
36 


posted on 2010-04-08 12:27 koson 阅读(2249) 评论(0)  编辑 收藏 引用 所属分类: ACM

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理