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

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

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

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

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

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

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

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

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

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

  1. #include <cstdio>
  2. #include <queue>
  3. #include <algorithm>
  4.  
  5. using namespace std;
  6.  
  7. const int N = ;
  8.  
  9. int n, m;
  10. int fa[N], vis[N];
  11. vector<int> g[N], ans;
  12.  
  13. int Sk(int x) {
  14. return fa[x] == x? x : fa[x] = Sk(fa[x]);
  15. }
  16.  
  17. void Bfs(int s) {
  18. static queue<int> Q;
  19. Q.push(s), fa[s] = Sk(s + );
  20. ans.push_back();
  21. for (int x; !Q.empty(); ) {
  22. x = Q.front(), Q.pop();
  23. for (int v : g[x]) vis[v] = x;
  24. for (int i = Sk(); i <= n; i = Sk(i + )) {
  25. if (vis[i] != x) fa[i] = Sk(i + ), Q.push(i), ++ans.back();
  26. }
  27. }
  28. }
  29.  
  30. int main() {
  31. scanf("%d%d", &n, &m);
  32. for (int i = , x, y; i <= m; ++i) {
  33. scanf("%d%d", &x, &y);
  34. g[x].push_back(y), g[y].push_back(x);
  35. }
  36. for (int i = ; i <= n; ++i) fa[i] = i;
  37. fa[n + ] = n + ;
  38. for (int i = ; i <= n; i = Sk(i + )) Bfs(i);
  39. sort(ans.begin(), ans.end());
  40. printf("%d\n", (int)ans.size());
  41. for (int i : ans) printf("%d ", i);
  42. putchar('\n');
  43.  
  44. return ;
  45. }

【BZOJ 1098】办公楼(补图连通块个数,Bfs)的更多相关文章

  1. Codeforces 920E Connected Components? 补图连通块个数

    题目链接 题意 对给定的一张图,求其补图的联通块个数及大小. 思路 参考 ww140142. 维护一个链表,里面存放未归入到任何一个连通块中的点,即有必要从其开始进行拓展的点. 对于每个这样的点,从它 ...

  2. 求连通块个数 - BFS、DFS、并查集实现

    本文基于leetcode的200.岛屿数量(题目

  3. P1197 [JSOI2008]星球大战 [删边求连通块个数]

    展开 题目描述 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系. 某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过特殊的 ...

  4. ZOJ 1709 Oil Deposits(dfs,连通块个数)

    Oil Deposits Time Limit: 2 Seconds      Memory Limit: 65536 KB The GeoSurvComp geologic survey compa ...

  5. bzoj 1098 办公楼biu —— 链表+栈

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1098 首先,没有连边的人一定得在一个连通块里: 先把所有人连成一个链表,然后从第一个人开始, ...

  6. bzoj 1015 维护连通块个数,离线并查集

    水. /************************************************************** Problem: 1015 User: idy002 Langua ...

  7. DFS:POJ1562-Oil Deposits(求连通块个数)

    Oil Deposits Time Limit: 1000MS Memory Limit: 10000K Description The GeoSurvComp geologic survey com ...

  8. BZOJ 1098: [POI2007]办公楼biu 链表

    求补图连通块,用链表优化,势能O(n+m) #include<cstdio> #include<cstring> #include<iostream> #inclu ...

  9. hdu 1241 Oil Deposits(DFS求连通块)

    HDU 1241  Oil Deposits L -DFS Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & ...

随机推荐

  1. jsp标签在JavaScript中使用时,可能会出现的一个问题。

    直接上代码 <script type="text/javascript"> var E = window.wangEditor; var editor = new E( ...

  2. 正则表达式的捕获组(Java)

    捕获组分类 普通捕获组(Expression) 命名捕获组(?<name>Expression) 普通捕获组 从正则表达式左侧开始,每出现一个左括号“(”记做一个分组,分组编号从1开始.0 ...

  3. date命令详解

    基础命令学习目录首页 原文链接:https://www.cnblogs.com/qmfsun/p/4598650.html date "+今天是%Y-%d-%m,现在是%H:%M:%S&qu ...

  4. Tornado之笔记集合

    目录 一.基本使用 二.路由系统 三.视图函数 四.模版语言 五.cookie 六.CSRF 七.文件上传 八.异步非阻塞 九.RESTFUL 十.自定义组件 一.基本使用 1.最简使用 import ...

  5. ### Error building SqlSession.

    org.apache.ibatis.exceptions.PersistenceException: ### Error building SqlSession.### The error may e ...

  6. spring冲刺第十天

    调试运行,对整体的游戏方面进行改进.冲刺完了,但依然有很多问题,比如无法暂停,游戏结束后只能退出重来等

  7. C++自学随笔

    主要学习内容: 了解了IDE环境的含义 C++与C的区别: 新的数据类型:bool型 新的初始化方法:直接初始化int x(1024) 经过查找,了解了直接初始化与复制初始化的区别:"当用于 ...

  8. DPDK L3fwd 源码阅读

    代码部分 整个L3fwd有三千多行代码,但总体思想就是在L2fwd的基础上,增加网络层的根据 IP 地址进行路由查找的内容. main.c 文件 int main(int argc, char **a ...

  9. ejb与javabean的区别总结

    EJB的英文全称是企业级的JavaBean 两者是完全不同的 JavaBean是一个组件,而EJB就是一个组建框架 JavaBean面向的是业务逻辑和表示层的显示,通过编写一个JavaBean,可以将 ...

  10. keil c51笔记

    第一章 Keil C51开发系统基本知识 第一节 系统概述 Keil C51是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上.结构性.可读性. ...