小z的洞穴之旅 QDUOJ 并查集+连通块

原题链接

题意

小 z 同学在某个闲暇的周末决定去野外探险一波,结果在丛林深处中误打误撞进入了一个神秘的洞穴,虽然洞穴中光线昏暗,但小 z 凭借其敏锐的眼力立刻辨认出这是一个迷宫状洞穴,并且他还发现了一个现象:该洞穴中时不时会有一个墙块自行坍塌,每个墙体坍塌后其所在单元格即变为空地,其坍塌过程中所产生的尘土也会随之传到该墙体相连的各个空地处,于是他很好奇,对于每一次墙块的坍塌,所产生的尘土会遍及到多大的空白区域?

解题思路

这个题很像《啊哈!算法》中的岛屿问题,但是如果每次有墙倒塌后都进行BFS一次的话会超时,所以这里要先进行预处理,这里预处理是用bfs来扫,把联通的块使用并查集归并到一起(对于二维的数据,需要转化为一维的数据,代码中的getid函数就是干这个的)。之后每次有墙倒塌就查看周围四个位置, 详情见代码实现。

在此也感谢ZYB学长的题解!当时没有尝试做,很忏愧。

代码实现

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<iostream>
  4. #include<algorithm>
  5. #include<queue>
  6. using namespace std;
  7. const int maxn=5e3+7;
  8. struct note{
  9. int fa, sum;
  10. }tre[maxn*maxn];
  11. struct node{
  12. int x, y;
  13. };
  14. int n, m;
  15. char mp[maxn][maxn];
  16. int go[4][2]={1, 0, 0, 1, -1, 0, 0, -1};
  17. queue<node> q;
  18. inline int getid(int x, int y)// getid()将二维点(x,y)映射为一维的数值
  19. {
  20. return (x-1)*m + y;
  21. }
  22. int find(int x) //寻找父节点,并且进行路径压缩
  23. {
  24. if(tre[x].fa==x) return x;
  25. else return tre[x].fa = find(tre[x].fa);
  26. }
  27. void merge(int u, int v) //这里合并时按照各自集合中点的个数来进行合并
  28. {
  29. u=find(u);
  30. v=find(v);
  31. if(u==v) return ;
  32. if(tre[u].sum >= tre[v].sum)
  33. {
  34. tre[v].fa=u;
  35. tre[u].sum+=tre[v].sum;
  36. }
  37. else {
  38. tre[u].fa=v;
  39. tre[v].sum+=tre[u].sum;
  40. }
  41. }
  42. void bfs(int x, int y, int rt) //预处理中的一部分
  43. {
  44. while(!q.empty()) q.pop() ;
  45. node h={x, y}, tmp;
  46. int tx, ty, id;
  47. q.push(h);
  48. while(!q.empty())
  49. {
  50. h=q.front();
  51. q.pop() ;
  52. for(int i=0; i<4; i++)
  53. {
  54. tx=h.x+go[i][0];
  55. ty=h.y+go[i][1];
  56. if(tx<=0 || tx>n || ty<=0 || ty>m || mp[tx][ty]=='#')
  57. continue;
  58. id=getid(tx, ty);
  59. if(tx==x && ty==y || tre[id].fa!=id) continue;
  60. merge(rt, id);
  61. tmp.x=tx;
  62. tmp.y=ty;
  63. q.push(tmp);
  64. }
  65. }
  66. }
  67. void init() //预处理的主程序
  68. {
  69. int id;
  70. for(int i=1; i<=n; i++)
  71. for(int j=1; j<=m; j++)
  72. {
  73. id=getid(i, j);
  74. tre[id].fa=id; //默认父节点都是自己
  75. tre[id].sum=1;//默认个数都是1
  76. }
  77. for(int i=1; i<=n; i++)
  78. for(int j=1; j<=m; j++)
  79. {
  80. id=getid(i, j);
  81. // fa[tmp]!=tmp即表示该块已被遍历过
  82. if(mp[i][j]=='#' || tre[id].fa != id) continue;
  83. bfs(i, j, id);
  84. }
  85. }
  86. int main()
  87. {
  88. int q, x, y, tx, ty, id, tmp;
  89. scanf("%d%d", &n, &m);
  90. for(int i=1; i<=n; i++)
  91. scanf("%s", mp[i]+1);
  92. init();
  93. scanf("%d", &q);
  94. while(q--)
  95. {
  96. scanf("%d%d", &x, &y);
  97. id=getid(x, y);
  98. //尝试将(x,y)点与周围上下左右四个区域合并
  99. for(int i=0; i<4; i++)
  100. {
  101. tx=x+go[i][0];
  102. ty=y+go[i][1];
  103. if(tx<=0 || tx>n || ty<=0 || ty>m || mp[tx][ty]=='#')
  104. continue;
  105. tmp=getid(tx, ty);
  106. merge(id, tmp);
  107. }
  108. mp[x][y]='.'; //最后还需要维护原始的mp[][]
  109. printf("%d\n", tre[find(id)].sum); //返回当前点(x,y)所在的连通块的大小
  110. }
  111. return 0;
  112. }

小z的洞穴之旅 QDUOJ 并查集+连通块的更多相关文章

  1. 【BZOJ】2049: [Sdoi2008]Cave 洞穴勘测(lct/并查集)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2049 bzoj挂了..在wikioi提交,,1A-写lct的速度越来越快了-都不用debug-- 新 ...

  2. BZOJ_2049_[Sdoi_2008]_Cave_洞穴勘测_(LCT/并查集)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=2049 给出一个森林,起始互不相连,现在有link和cut两种操作,问x,y是否在一棵树里. 分 ...

  3. 小Z的城市之旅

    题目大意: 从(0,0)走到(x,y),每次可以向上下左右走一格,问走r步刚好到(x,y)的方案数. 思路: 找规律发现答案就是C((r+x-y)/2,r)*C((r-x-y)/2,r). #incl ...

  4. BZOJ 2038: [2009国家集训队]小Z的袜子(hose) [莫队算法]【学习笔记】

    2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 7687  Solved: 3516[Subm ...

  5. BZOJ 2038: [2009国家集训队]小Z的袜子(hose)

    2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 7676  Solved: 3509[Subm ...

  6. BZOJ2038: [2009国家集训队]小Z的袜子(hose)

    Time Limit: 20 Sec  Memory Limit: 259 MB Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天, ...

  7. Bzoj 2038---[2009国家集训队]小Z的袜子(hose) 莫队算法

    题目链接 http://www.lydsy.com/JudgeOnline/problem.php?id=2038 Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色 ...

  8. 莫队算法 2038: [2009国家集训队]小Z的袜子(hose)

    链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2038 2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 ...

  9. BZOJ 2038 小z的袜子 & 莫队算法(不就是个暴力么..)

    题意: 给一段序列,询问一个区间,求出区间中.....woc! 贴原题! 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过 ...

随机推荐

  1. 解决IDEA Initialization error 'https://start.spring.io'

    IDEA Initialization error  'https://start.spring.io'     弹出一个error窗口    就是不能连接https://start.spring.i ...

  2. PHP 字符串相关常识

    0x00 前言 第一次遇见字符串这个概念是在学 C 语言的时候,那时候觉得字符串也没有什么难的,不就是一个以 \0 结尾的 char 数组而已咯.后来在学习 PHP 的过程中也同样保持这个观念,不过在 ...

  3. C++STL中的unique函数

    头文件:#include<iostream> 函数原型:iterator unique(iterator it_1,iterator it_2); 作用:元素去重,即”删除”序列中所有相邻 ...

  4. 【BZOJ4570】 [Scoi2016]妖怪

    Description 邱老师是妖怪爱好者,他有n只妖怪,每只妖怪有攻击力atk和防御力dnf两种属性.邱老师立志成为妖怪大师,于 是他从真新镇出发,踏上未知的旅途,见识不同的风景.环境对妖怪的战斗力 ...

  5. dell笔记本 win10 下安装 ubuntu16.04 踩坑记录

    硬件配置情况: dell笔记本-灵越-5577 —— I5七代(带有集显),8G内存条DDR4,GTX1050,128G固态硬盘,1T机械硬盘. 固态硬盘划分为3部分,100GB给win10的C盘,1 ...

  6. 【Leetcode】整数反转

    题解参考:https://leetcode-cn.com/problems/reverse-integer/solution/zheng-shu-fan-zhuan-by-leetcode/ 复杂度分 ...

  7. swiper实现滑动到某页锁住不让滑动

    var swiper = new Swiper('.swiper-container', { pagination: '.swiper-pagination', onTouchStart: funct ...

  8. ali之monkey学习

    monkey主要用来进行压力测试,稳定性测试 http://www.cnblogs.com/yyangblog/archive/2011/03/10/1980068.html 1,什么是monkey ...

  9. TCP与UDP的对比分析

    转自该地址:https://blog.csdn.net/birdie_l/article/details/78067896 TCP: 优点:可靠 稳定 TCP的可靠体现在TCP在传输数据之前,会有三次 ...

  10. js的浅拷贝和深拷贝和应用场景

    为什么会用到浅拷贝和深拷贝 首先来看一下如下代码 let a = b = 2 a = 3 console.log(a) console.log(b) let c = d = [1,2,3] let e ...