补图连通块个数这大概是一个套路吧,我之前没有见到过,想了好久都没有想出来QaQ

事实上这个做法本身就是一个朴素算法,但进行巧妙的实现,就可以分析出它的上界不会超过 $O(n + m)$。

接下来介绍一下这个技巧:

很显然一个不在原图中的边一定在补图中出现,如果我们考虑用朴素的$Bfs$求一个图中的连通块个数,对于当前的一个点$x$,枚举它连出去的边进行拓展即可。

如果是求补图中的,那对于当前队首的点$x$,可以枚举其他所有的点,看是否和这个点有连边,没有就拓展。

一个可以的优化就是,一个点在$Bfs$是不会被入队多次,我们可以把它删掉,这样可以优化原先朴素算法在拓展上$O(n)$枚举的复杂度。

至于为什么删掉不会造成问题,我们可以考虑它有可能存在的问题就是某一个点$x$在拓展的时候准备拓展一个已经被删除的点$y$,那可能会造成原本在一个连通块的点分成多个,这种情况下在之前$y$拓展的时候就会先拓展到$x$;至于如果两个点同时被删除时,那它们一定是同一个根,一定是同一个连通块里的。

接下来证明这样优化之后复杂度的上界是$O(n + m)$:

事实上我们进行每一次拓展的时候,一次失败的拓展是因为原图中存在着这条边,而一旦拓展成功,就能删掉一个点。由于每条边做多被访问一次,于是每次拓展就是要么是减少一条边,要么是减少一个点,故$Bfs$的复杂度上界是$O(n + m)$的。

这个题就是一个例子,在此做一个总结:

#include <cstdio>
#include <queue>
#include <algorithm>using namespace std;const int N = 100005;int n, m;
int fa[N], vis[N];
vector<int> g[N], ans;int Sk(int x) {return fa[x] == x? x : fa[x] = Sk(fa[x]);
}void Bfs(int s) {static queue<int> Q;Q.push(s), fa[s] = Sk(s + 1);ans.push_back(1);for (int x; !Q.empty(); ) {x = Q.front(), Q.pop();for (int v : g[x]) vis[v] = x;for (int i = Sk(1); i <= n; i = Sk(i + 1)) {if (vis[i] != x) fa[i] = Sk(i + 1), Q.push(i), ++ans.back();}}
}int main() {scanf("%d%d", &n, &m);for (int i = 1, x, y; i <= m; ++i) {scanf("%d%d", &x, &y);g[x].push_back(y), g[y].push_back(x);}for (int i = 1; i <= n; ++i) fa[i] = i;fa[n + 1] = n + 1;for (int i = 1; i <= n; i = Sk(i + 1)) Bfs(i);sort(ans.begin(), ans.end());printf("%d\n", (int)ans.size());for (int i : ans) printf("%d ", i);putchar('\n');return 0;
}

View Code

转载于:https://www.cnblogs.com/Dance-Of-Faith/p/9648930.html

【BZOJ 1098】办公楼(补图连通块个数,Bfs)相关推荐

  1. 求连通块个数(使用并查集)

    并查集求连通块个数的模板 #include<bits/stdc++.h>using namespace std;const int maxn = 1e5+5; vector<int& ...

  2. 【CodeForces - 920E】Connected Components? (dsu,补图连通块,STLset+map,bfs 或bitset)

    题干: You are given an undirected graph consisting of n vertices and  edges. Instead of giving you the ...

  3. [C] 深度优先搜索解决连通块/染色问题——求岛的个数

    本文介绍用DFS解决连通块个数问题 有关dfs的介绍见另外一篇:不撞南墙不回头--深度优先搜索 例题 宝岛探险 题目描述 一个小岛由一个主岛和一些复附属岛屿组成,该岛使用一个二维矩阵表示,其中数字表示 ...

  4. 算法提高课-搜索-Flood fill算法-AcWing 1098. 城堡问题:flood fill、bfs

    题目分析 来源:acwing 分析:找房间个数,也就是找连通的个数. 样例画出来的房间个数如下图:其中'|' 和'-'不是墙,只有#是墙. 分析:这题不用建图,直接bfs(flood fill)来做, ...

  5. 图论 —— 环与块 —— 连通块的计数

    [概述] 对于给出 n 个点 m 条边的图来说,对任意两点,从顶点 Vi 到顶点 Vj 有路径,则称 Vi 和 Vj 是连通的,两者可视为一个连通块,因此,连通块的计数本质就是求其连通分量,可采用 d ...

  6. 信息学奥赛一本通 1335:【例2-4】连通块

    [题目链接] ybt 1335:[例2-4]连通块 [题目考点] 1. 搜索:连通块问题 [解题思路] 设数组vis,vis[i][j]表示(i,j)位置已经访问过. 遍历地图中的每个位置,尝试从每个 ...

  7. 【牛客 - 368D】动态连通块(并查集+bitset优化)

    题干: 小T有n个点,每个点可能是黑色的,可能是白色的. 小T对这张图的定义了白连通块和黑连通块: 白连通块:图中一个点集V,若满足所有点都是白点,并且V中任意两点都可以只经过V中的点互相到达,则称V ...

  8. [BZOJ 1098] [POI2007] 办公楼biu 【链表优化BFS】

    题目链接:BZOJ - 1098 题目分析 只有两个点之间有边的时候它们才能在不同的楼内,那么就是说如果两个点之间没有边它们就一定在同一座楼内. 那么要求的就是求原图的补图的连通块. 然而原图的补图的 ...

  9. 1335:【例2-4】连通块——dfs、bfs

    [题目描述] 一个n × m的方格图,一些格子被涂成了黑色,在方格图中被标为1,白色格子标为0.问有多少个四连通的黑色格子连通块.四连通的黑色格子连通块指的是一片由黑色格子组成的区域,其中的每个黑色格 ...

最新文章

  1. 64位环境启用ASP.net 2.0的32位扩展
  2. linux c 笔记 文件(二)
  3. 自动化测试学习笔记(一)HTML概念
  4. iOS开发之段落文字排版的属性与细节
  5. HUffman树学习笔记
  6. matlab-plot绘制点线图
  7. OBS直播影视使用虚拟声卡
  8. 个人学习C语言的目标
  9. java计算机毕业设计济南旅游网站源码+mysql数据库+系统+lw文档+部署
  10. java开发面试流程
  11. matlab列主元消去法求逆矩阵,Gauss-Jordan列主元消元法求逆矩阵
  12. mysql查询出现ambiguous的问题
  13. 网络视频广告今年起步
  14. 关于Data Matrix 基于ECC200标准的编码原理和相关开源代码
  15. 计算机专业有哪些有含金量的证书,大学最有含金量的6大类证书!你拥有哪几个?...
  16. 自定义Navigator切换fragment
  17. Oracle 储存生僻字
  18. C# 实现预览dwg文件完整源代码(无需autocad环境)
  19. 正点原子linux串口驱动下载,【正点原子Linux连载】第二十一章UART串口通信实验-摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南 (amobbs.com 阿莫电子论坛)...
  20. L2-001 紧急救援

热门文章

  1. Hibernate---对象的三种状态
  2. .Net Core 简洁架构事件(这个不完整,待仔细补充)
  3. P2216 [HAOI2007]理想的正方形(二维RMQ)
  4. bootstrap在ie8下,兼容媒体查询
  5. redis aof持久化遇到的Can't open the append-only file Permissi
  6. sql性能优化之多表联查
  7. 使自定义控件居中于父容器的计算公式
  8. solr4.6本地数据提交异常
  9. [C++ rudiment][转]typedef 使用
  10. 阿里云应用实战-IoT工业数据上云优化实践