【bzoj1098】办公楼
【bzoj1098】办公楼
题意
FGD开办了一家电话公司。他雇用了N个职员,给了每个职员一部手机。每个职员的手机里都存储有一些同事的电话号码。由于FGD的公司规模不断扩大,旧的办公楼已经显得十分狭窄,FGD决定将公司迁至一些新的办公楼。FGD希望职员被安置在尽量多的办公楼当中,这样对于每个职员来说都会有一个相对更好的工作环境。但是,为了联系方便起见,如果两个职员被安置在两个不同的办公楼之内,他们必须拥有彼此的电话号码。
\(2<=N<=100000,1<=M<=2000000\)
分析
要求块内任意,块外充满连边的最小划分数。
那就等价于补图上块内任意,块外无连边的最小划分数。
那么就等价于求补图的联通块个数。
对\(n=100000\)的稠密图来讲,
直接求联通块会炸。
所以要利用到\(M\leq 2000000\)的特性。
我最初的想法是:我们可以枚举任意一对的\((i,j)\),若它们在原图中不存在连边,那么用并查集把它们合并。
由于这是一幅稠密图,所以\((i,j)\)有很大的概率存在连边,所以我们对于每个点\(i\),不需要枚举所有的\(j\),只需要随机枚举\(T\)个,然后尝试连边即可。
然而WA了......
接下来说的是正解。
求连通块的方法常有搜索或者并查集。
并查集看似不行,我们考虑搜索的过程,并根据\(M\leq 2000000\)的特性优化。
BFS:对于一个点\(i\),找与它连通的所有点\(j\),再找与\(j\)连通的所有点\(k\)......
把所有找到的点删去,ans++。
普通的实现上,最大的瓶颈在于已经删除的点我们还反复枚举了......
那么我们就不反复枚举好了,直接使用双向链表来删点,复杂度就优化到了\(O(n)\),因为最多有\(2M\)次失败。
还看到一种更精彩的代替双向链表的做法。
就是直接使用并查集代替双向链表。
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
#include <vector>
using namespace std;
#define rep(i,a,b) for (int i=(a);i<=(b);i++)
const int N=131072;
int n,m;
vector<int> g[N];
int vis[N],f[N];
int cnt[N],len;
int hsn[N],q[N],qh,qt;
int rd(void) {
int x=0,f=1; char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
int Find(int x) {
if (f[x]==x) return x;
return f[x]=Find(f[x]);
}
void Erase(int st) {
qh=qt=0; q[++qt]=st; vis[st]=1;
cnt[len]++;
f[st]=Find(st+1);
while (qh!=qt) {
int x=q[++qh];
rep(i,1,g[x].size()) {
int nx=g[x][i-1];
hsn[nx]=1;
}
int nx=Find(1);
while (nx!=n+1) {
if (!hsn[nx]) {
q[++qt]=nx; vis[nx]=1; cnt[len]++;
f[nx]=Find(nx+1);
}
nx=Find(nx+1);
}
rep(i,1,g[x].size()) {
int nx=g[x][i-1];
hsn[nx]=0;
}
}
}
int main(void) {
#ifndef ONLINE_JUDGE
freopen("sd.in","r",stdin);
freopen("sd.out","w",stdout);
#endif
n=rd(),m=rd();
rep(i,1,m) {
int x=rd(),y=rd();
g[x].push_back(y),g[y].push_back(x);
}
rep(i,1,n+1) f[i]=i;
rep(i,1,n) if (!vis[i]) {
len++;
Erase(i);
}
sort(cnt+1,cnt+len+1);
printf("%d\n",len);
rep(i,1,len)
printf("%d ",cnt[i]);
printf("\n");
return 0;
}
小结
(1)并查集可以代替双向链表,且实现更容易。
(2)外界充满边=补图外界无边,注意充满边的转化方法,最大团也是充满边的一种体现形式。
(3)连通块个数的统计,通常使用并查集或者搜索实现。
【bzoj1098】办公楼的更多相关文章
- bzoj1098 办公楼
Description FGD开办了一家电话公司.他雇用了N个职员,给了每个职员一部手机.每个职员的手机里都存储有一些同事的电话号码.由于FGD的公司规模不断扩大,旧的办公楼已经显得十分狭窄,FGD决 ...
- 5098: [BZOJ1098][POI2007]办公楼biu
5098: [BZOJ1098][POI2007]办公楼biu 没有数据结构就很棒 一个看上去非常玄学的代码 const int N=1e5+10,M=2e6+10; int n,m; int fa[ ...
- BZOJ1098: [POI2007]办公楼biu
从问题可以看出是求补图的连通块及点数 但补图太大.所以考虑缩小规模. 当一个点归属于一个连通块后,它以后就不需要了.所以可以用链表,删去这个点,也就减小了规模. 一个点开始bfs,每个点只会进队一次, ...
- 【链表】Bzoj1098[POI2007]办公楼biu
Description FGD开办了一家电话公司.他雇用了N个职员,给了每个职员一部手机.每个职员的手机里都存储有一些同事的电话号码.由于FGD的公司规模不断扩大,旧的办公楼已经显得十分狭窄,FGD决 ...
- BZOJ1098 POI2007 办公楼biu 【链表+bfs】
Description FGD开办了一家电话公司.他雇用了N个职员,给了每个职员一部手机.每个职员的手机里都存储有一些同事的电话号码.由于FGD的公司规模不断扩大,旧的办公楼已经显得十分狭窄,FGD决 ...
- 【BZOJ1098】[POI2007]办公楼biu
题目一开始看以为和强联通分量有关,后来发现是无向边,其实就是求原图的补图的联通块个数和大小.学习了黄学长的代码,利用链表来优化,其实就是枚举每一个人,然后把和他不相连的人都删去放进同一个联通块里,利用 ...
- 【BZOJ1098】办公楼biu(补图,bfs,链表)
题意:有n个点m条边,要求将点尽可能多的分成若干个部分,使得若两个点不在同一个部分则他们之间必定有边 n<=1e5,m<=2e6 思路:From https://blog.csdn.net ...
- 【BZOJ】1098: [POI2007]办公楼biu(补图+bfs+链表)
http://www.lydsy.com/JudgeOnline/problem.php?id=1098 显然答案是补图连通块..... 想到用并查集...可是连补图的边都已经...n^2了...怎么 ...
- 办公楼[POI2007]
题目描述 FGD开办了一家电话公司.他雇用了N个职员,给了每个职员一部手机.每个职员的手机里都存储有一些同事的电话号码.由于FGD的公司规模不断扩大,旧的办公楼已经显得十分狭窄,FGD决定将公司迁至一 ...
随机推荐
- 如何让VMware低版本运行VMware高版本创建的虚拟机
如何让VMware低版本运行VMware高版本创建的虚拟机 问题描述: 本机安装的VMware Workstation是10版本,之前VMware Workstation 11版本创建的虚拟机,在运行 ...
- IntelliJ IDEA Community Edition 14.1.4下使用 Apache-Subversion搭建代码管理环境
当前我的idea 版本是14.1.4. 1,)SVN Server下载与安装(https://www.visualsvn.com/server/): 因为我开发机是x64的,所以我优先下载 x64的 ...
- linux下svn服务器安装配置与启动
1. 采用源文件编译安装.源文件共两个,为: subversion-1.6.1.tar.gz (subversion 源文件) subversion-deps-1.6.1.tar.gz (subv ...
- 《zw版·Halcon-delphi系列原创教程》简单的令人发指,只有10行代码的车牌识别脚本
<zw版·Halcon-delphi系列原创教程>简单的令人发指,只有10行代码的车牌识别脚本 简单的令人发指,只有10行代码的车牌识别脚本 人脸识别.车牌识别是opencv当中 ...
- zw版·全程图解Halcon控件安装(delphi2007版)
zw版·全程图解Halcon控件安装(delphi2007版) delphi+halcon,这个组合,可以说是图像分析的神级配置,无论是开发效率,还是运行实在是太高了,分分钟秒杀c+opencv,py ...
- 关于华擎X99+5820K
受到之前Intel I7-5775C的困扰,于是直接整套平台换掉. 把Z97+I7-5775C+DDR3换成了X99+5820K+DDR4. 但是依然不理想,又是另外一个坑. 组装好后安装系统的过程 ...
- 自定义view imageviw
新建一个类继承imageview package com.exaple.myselfview; import android.content.Context; import android.graph ...
- python实现动态更新远程机器列表的SSH登录脚本
在公司里, 常常要远程到很多机器上执行命令.机器列表会逐渐增多, 记忆这么多机器的IP或域名显然不是人脑所擅长的.因此, 需要保持一份SSH机器列表,从这些机器列表生成一个用于SSH到机器列表中机器的 ...
- Application.DoEvents():概念
When you run a Windows Form, it creates the new form, which then waits for events to handle. Each ti ...
- 关于使用nuget的部分代码
Install-Package 安装包 -Version 4.3.1 参数指定版本 Uninstall-Package 卸载包 Update-Package 更新包 Get-Package 默认列出本 ...