[BZOJ 1098] [POI2007] 办公楼biu 【链表优化BFS】
题目链接:BZOJ - 1098
题目分析
只有两个点之间有边的时候它们才能在不同的楼内,那么就是说如果两个点之间没有边它们就一定在同一座楼内。
那么要求的就是求原图的补图的连通块。
然而原图的补图的边数是 n^2 级别的,非常庞大,我们不能直接把补图求出来。
可以使用一种用链表优化BFS的做法,开始时将所有的点加到一个链表里。
每次找一个连通块的时候BFS,在链表中取出一个点,在链表中删除,加入队列,然后每次取出队首元素x,枚举x的每一条边,将边的终点y从链表中删去,加到一个临时的链表中存储。
这样枚举完 x 的所有边之后,原链表里剩余的点就是与 x 没有边的,这些点在补图里与 x 就是有边的,将这些点加入队列。
然后用临时的链表替代原链表,原链表中就是剩下的点了。
这样BFS几次就可以求出所有连通块了。
每一个点都只被从链表中删去1次,每条边都只遍历了一次,总的时间复杂度是 O(n + m)。
代码
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <queue> using namespace std; const int MaxN = 100000 + 5, MaxM = 2000000 + 5; inline void Read(int &Num)
{
char c; c = getchar();
while (c < '0' || c > '9') c = getchar();
Num = c - '0'; c = getchar();
while (c >= '0' && c <= '9')
{
Num = Num * 10 + c - '0';
c = getchar();
}
} int n, m, Top, R1, R2, Sum;
int Ans[MaxN], Last[MaxN], Next[MaxN]; bool InList[MaxN]; struct Edge
{
int v;
Edge *Next;
} E[MaxM * 2], *P = E, *Point[MaxN]; inline void AddEdge(int x, int y)
{
++P; P -> v = y;
P -> Next = Point[x]; Point[x] = P;
} queue<int> Q; inline void Add(int x, int y)
{
Next[y] = Next[x];
if (Next[x]) Last[Next[x]] = y;
Next[x] = y;
Last[y] = x;
} inline void Delete(int x)
{
if (Last[x]) Next[Last[x]] = Next[x];
if (Next[x]) Last[Next[x]] = Last[x];
} void BFS()
{
while (!Q.empty()) Q.pop();
Q.push(Next[R1]);
InList[Next[R1]] = false;
Delete(Next[R1]);
int x, y;
++Top;
while (!Q.empty())
{
x = Q.front();
++Sum;
++Ans[Top];
Q.pop();
R2 = n + 2;
Last[R2] = Next[R2] = 0;
for (Edge *j = Point[x]; j; j = j -> Next)
{
y = j -> v;
if (!InList[y]) continue;
Delete(y);
Add(R2, y);
}
for (int i = Next[R1]; i; i = Next[i])
{
Q.push(i);
InList[i] = false;
}
Next[R1] = Next[R2];
Last[Next[R1]] = R1;
}
} int main()
{
scanf("%d%d", &n, &m);
int a, b;
for (int i = 1; i <= m; ++i)
{
Read(a); Read(b);
AddEdge(a, b);
AddEdge(b, a);
}
Top = 0; Sum = 0;
R1 = n + 1;
for (int i = 1; i <= n; ++i) Add(R1, i);
for (int i = 1; i <= n; ++i) InList[i] = true;
while (Sum < n) BFS();
printf("%d\n", Top);
sort(Ans + 1, Ans + Top + 1);
for (int i = 1; i <= Top; ++i) printf("%d ", Ans[i]);
return 0;
}
[BZOJ 1098] [POI2007] 办公楼biu 【链表优化BFS】的更多相关文章
- BZOJ 1098: [POI2007]办公楼biu 链表
求补图连通块,用链表优化,势能O(n+m) #include<cstdio> #include<cstring> #include<iostream> #inclu ...
- BZOJ 1098 [POI2007]办公楼biu(反向图bfs+并查集优化)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1098 [题目大意] 现在有一张图,要求将这张图的点划分为尽量多的分组,对于不同分组的两 ...
- bzoj 1098 [POI2007]办公楼biu——链表
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1098 求补图的连通块大小.与自己没有边的和自己在一个连通块里. 用链表把所有点串起来.先给自 ...
- BZOJ_1098_[POI2007]办公楼biu_链表优化BFS
BZOJ_1098_[POI2007]办公楼biu_链表优化BFS Description FGD开办了一家电话公司.他雇用了N个职员,给了每个职员一部手机.每个职员的手机里都存储有一些同事的 电话号 ...
- bzoj 1098 [POI2007]办公楼biu bfs+补图+双向链表
[POI2007]办公楼biu Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 1543 Solved: 743[Submit][Status][Di ...
- 【BZOJ】1098: [POI2007]办公楼biu(补图+bfs+链表)
http://www.lydsy.com/JudgeOnline/problem.php?id=1098 显然答案是补图连通块..... 想到用并查集...可是连补图的边都已经...n^2了...怎么 ...
- bzoj 1098 [POI2007] 办公楼 biu
# 解题思路 画画图可以发现,只要是两个点之间没有相互连边,那么就必须将这两个人安排到同一个办公楼内,如图所示: 那,我们可以建立补图,就是先建一张完全图,然后把题目中给出的边都删掉,这就是一张补图, ...
- 【刷题】BZOJ 1098 [POI2007]办公楼biu
Description FGD开办了一家电话公司.他雇用了N个职员,给了每个职员一部手机.每个职员的手机里都存储有一些同事的 电话号码.由于FGD的公司规模不断扩大,旧的办公楼已经显得十分狭窄,FGD ...
- bzoj 1098 poi2007 办公楼 bfs+链表
题意很好理解,求给出图反图的联通块个数. 考虑这样一个事情:一个联通块里的点,最多只会被遍历一次,再遍历时没有任何意义 所以用链表来存,每遍历到一个点就将该点删掉 #include<cstdio ...
随机推荐
- Cocos2d-x游戏中默认的AndroidManifest.xml的解析
直接上代码说明: <?xml version="1.0" encoding="utf-8"? > <!-- xmlns:android=&qu ...
- 64位开源处理器Rocket该人士介绍
最近大概读一点UCB发布时间Rocket处理器的源代码,的每个文件的源代码的功能有一定的一般理解,Mark一点点. Rocket是一家64bit标量处理器,5第一阶段管道,用途risc-v指令集.综合 ...
- 如何调试PHP的Core之获取基本信息 --------风雪之隅 PHP7核心开发者
http://www.laruence.com/2011/06/23/2057.html https://github.com/laruence PHP开发组成员, Zend兼职顾问, PHP7核心开 ...
- JS家的排序算法
由于浏览器的原生支持(无需安装任何插件),用JS来学习数据结构和算法也许比c更加便捷些.因为只需一个浏览器就能啪啪啪的调试了.比如下图我学习归并排序算法时,只看代码感觉怎么都理解不了,但是结合chro ...
- hdu2015java
偶数求和 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submissio ...
- 以非root权限安装nginx及运行
本章主要讲如何在无root权限(包含无sudo权限)条件下于centos命令行中安装nginx以及在大于1024的端口(这里用8080)上运行. 1. 安装 两种方式,一是下载预编译好的rpm包安装, ...
- C# QRCode、DataMatrix和其他条形码的生成和解码软件
今天制造了一个C#的软件,具体是用于生成二维码和条形码的,包括常用的QRCode.DataMatrix.Code128.EAN-8等等. 使用的第三方类库是Zxing.net和DataMatrix.n ...
- SQL删除重复行和查询所有大于某成绩的语句分析
有这样一个题,用一条SQL语句 查询出每门课都大于80分的学生姓名. 下面是表 分析,查询每门课程都大于80的学生.SELECT DISTINCT name FROM dbo.student WHER ...
- Http协议、线程、线程池
Socket模拟服务端运行代码: 1:启动服务端监听的服务,并接受客户端的连接 1.1 创建Socket Socket listenSocket=new Socket(AddressFamily.In ...
- js基础知识之_函数
javascript函数 函数概念 将完成某一特定功能的代码集合起来,可以重复使用 白话函数理解-函数就是一个工厂,帮大家实现某一个功能 优点 -时程序更加简洁 -逻辑更有条例 -调用方便 -维护更加 ...