补图连通块个数这大概是一个套路吧,我之前没有见到过,想了好久都没有想出来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 = ; 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 + );
ans.push_back();
for (int x; !Q.empty(); ) {
x = Q.front(), Q.pop();
for (int v : g[x]) vis[v] = x;
for (int i = Sk(); i <= n; i = Sk(i + )) {
if (vis[i] != x) fa[i] = Sk(i + ), Q.push(i), ++ans.back();
}
}
} int main() {
scanf("%d%d", &n, &m);
for (int i = , x, y; i <= m; ++i) {
scanf("%d%d", &x, &y);
g[x].push_back(y), g[y].push_back(x);
}
for (int i = ; i <= n; ++i) fa[i] = i;
fa[n + ] = n + ;
for (int i = ; i <= n; i = Sk(i + )) Bfs(i);
sort(ans.begin(), ans.end());
printf("%d\n", (int)ans.size());
for (int i : ans) printf("%d ", i);
putchar('\n'); return ;
}

【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. Unity消息简易框架 Advanced C# messenger

    Unity消息简易框架 Advanced C# messenger Unity C# 消息机制  [转载 雨凇MOMO博客] https://www.xuanyusong.com/archives/2 ...

  2. 为centos虚拟机配置固定ip

    在virtual上安装centos虚拟机以后,发现虚拟机没有ip,无法联网 将虚拟机的网络适配器改为桥接模式,桥接到物理机的无线网卡 为虚拟机配置固定IP(vi /etc/sysconfig/netw ...

  3. SharpDevelop 笔记

    1. 下载地址: http://jaist.dl.sourceforge.net/project/sharpdevelop/ 2. 使用 VS2012 去掉编译不通过的 Test ,其它可以运行调试. ...

  4. alias命令详情

    基础命令学习目录首页 原文链接:http://c.biancheng.net/view/938.html 给命令设置别名,你可以把它当作命令的"小名",但是这样做有什么意义呢? 比 ...

  5. Python中collections模块的使用

    本文将详细讲解collections模块中的所有类,和每个类中的方法,从源码和性能的角度剖析. 一个模块主要用来干嘛,有哪些类可以使用,看__init__.py就知道 '''This module i ...

  6. Daily Scrum (2015/10/25)

    今天终于到了周末的尾声,我们的组员也应该正常得投入到工作中了.这天晚上我(符美潇)和PM(潘礼鹏)和两个DEV开了一个小会,讨论一下我们本周的代码编写工作.我们了解到大家的代码阅读工作和相关知识的学习 ...

  7. Task 4.2 求一个矩阵的最大子矩阵的和

    任务:输入一个二维整形数组,数组里有正数也有负数.二维数组中连续的一个子矩阵组成一个子数组,每个子数组都有一个和.求所有子数组的和的最大值.要求时间复杂度为O(n). (1)设计思想:把二维矩阵分解成 ...

  8. String 类 的 使用

    package com.StringUse; import java.util.Arrays; /* String 的构造方法: String() 创建一个空内容 的字符串对象. String(byt ...

  9. Leetcode题库——1.两数之和

    @author: ZZQ @software: PyCharm @file: addTwoNumbers.py @time: 2018/9/18 10:35 要求:给定两个非空链表来表示两个非负整数. ...

  10. asp.net文件上传接收不到文件 Request.files["']等于null

    这个时候你应该检查下你的form表单里面是否配置了这个: enctype ="multipart/form-data"  新手容易出错哦. <form id="fo ...