zoukankan      html  css  js  c++  java
  • POJ1988 Cube Stacking 【并查集】

    题目链接:http://poj.org/problem?id=1988

    这题是教练在ACM算法课上讲的一道题,当时有地方没想明白,现在彻底弄懂了。

    题目大意:n代表有n个石头,M a, b代表将a石头所在的集合放在b石头所在的所有集合的上方。C a代表询问a石头下方有多少个石头。

    思路:

    1.一开始我是想用一个 num 数组来表示每块石头下方有多少个石头,然后直接用并查集来写,但是发现最终不能实现,因为只用一个num数组只能保证每个集合的最顶端的石头num值是正确的。

    2.正解是用一个 dis 数组代表每块石头到根节点石头的距离,num数组代表每块石头所在集合的石头总数,最终答案就是 num[find(a)] - dis[a] - 1;

    3.需要注意的地方是 先查找根节点 后更新dis以及num,因此在查询某一块石头下面有多少石头时,还需要进行一次 find 来更新一下路径上石头的dis。

    代码里的注释写的很详细

    代码:

     注意:数据好像比题面给的大,数组要开大点。

     1 #include<iostream>  //用cin输入无视空格和回车,方便判断操作 
     2 using namespace std;
     3 
     4 int num[300010], pre[300010], dis[300010];
     5 
     6 int find(int x)
     7 {
     8     if(pre[x] == x)
     9         return x;
    10     else
    11     {
    12         int root = find(pre[x]);
    13         dis[x] += dis[pre[x]];//下面的块中点到新根节点的距离为 原来的距离dis[x]加上被更新过的dis[root] = num[x]的距离 
    14         pre[x] = root;
    15         return pre[x];
    16     }
    17 }
    18 
    19 int main()
    20 {
    21     cin.sync_with_stdio(false);//关闭cin同步加速,但读入只能用cin了 
    22     int n;
    23     cin >> n;
    24     for(int i = 1; i <= n; i ++)
    25     {
    26         pre[i] = i;
    27         dis[i] = 0;//到根节点的距离 
    28         num[i] = 1;//每个块中包含的点数目 
    29     }
    30     while(n --)
    31     {
    32         char ch;
    33         cin >> ch;
    34         if(ch == 'M')
    35         {
    36             int a, b;
    37             cin >> a >> b;
    38             int x = find(a), y = find(b);//此时的find只是找到根节点,find()函数中各点dis值没有改变,因为此时根节点的dis为0 
    39             if(x != y) 
    40             {//注意顺序 
    41                 dis[y] = num[x];//这里才给根节点的dis值进行了更新,所以下次还需要调用一次find才能维护各点的dis值 
    42                 num[x] += num[y];//以x为根节点的块中数目更新为 以x和y为根节点的两个块中点的数目之和 
    43                 pre[y] = x;
    44             }
    45         }
    46         else if(ch == 'C')
    47         {
    48             int a;
    49             cin >> a;
    50             int x = find(a);//查询之前还需要进行一次 find 来更新块中各点的dis值 
    51             printf("%d
    ", num[x] - dis[a] - 1);
    52         }
    53     }
    54     return 0;
    55 }
    POJ1988
  • 相关阅读:
    mfc判断当前程序是否正在运行
    mfc通过信号量保证线程同步
    delete和析构函数
    获取当前运行的exe路径
    mfc移动文件夹
    Cmake实现样例
    安装Node.js以及Hexo
    分类与回归的关系和区别
    從文本到視覺:各領域最前沿的論文集合
    ubuntu 终端$换行
  • 原文地址:https://www.cnblogs.com/yuanweidao/p/10928308.html
Copyright © 2011-2022 走看看