BZOJ1098 POI2007 办公楼biu 【链表+bfs】
Description
FGD开办了一家电话公司。他雇用了N个职员,给了每个职员一部手机。每个职员的手机里都存储有一些同事的电话号码。由于FGD的公司规模不断扩大,旧的办公楼已经显得十分狭窄,FGD决定将公司迁至一些新的办公楼。FGD希望职员被安置在尽量多的办公楼当中,这样对于每个职员来说都会有一个相对更好的工作环境。但是,为了联系方便起见,如果两个职员被安置在两个不同的办公楼之内,他们必须拥有彼此的电话号码。
Input
第一行包含两个整数N(2<=N<=100000)和M(1<=M<=2000000)。职员被依次编号为1,2,……,N.以下M行,每行包含两个正数A和B(1<=A<b<=n),表示职员a和b拥有彼此的电话号码),li <= 1000
Output
包含两行。第一行包含一个数S,表示FGD最多可以将职员安置进的办公楼数。第二行包含S个从小到大排列的数,每个数后面接一个空格,表示每个办公楼里安排的职员数。
Sample Input
7 16
1 3
1 4
1 5
2 3
3 4
4 5
4 7
4 6
5 6
6 7
2 4
2 7
2 5
3 5
3 7
1 7
Sample Output
3
1 2 4
HINT
FGD可以将职员4安排进一号办公楼,职员5和职员7安排进2号办公楼,其他人进3号办公楼。
思路
容易发现这个问题就是求一个图里边少多能分成多少个块,使得每一个块中间都没有边相连
正向不好求,然后就考虑在补图上求联通块个数
然后就考虑用bfs的方法,但直接bfs时间效率是\(O(nm)\)的
所以可以用链表优化
这样当一个点被删除才会访问连接的边,所以时间效率就变成了\(O(n+m)\)
这个链表用法很神奇
#include<bits/stdc++.h>
using namespace std;
#define fu(a,b,c) for(int a=b;a<=c;++a)
#define fd(a,b,c) for(int a=b;a>=c;--a)
#define N 1000010
struct Block{int l,r,vis,mark;}b[N];
vector<int> g[N];
int n,m,ans=0,siz[N];
void add(int u,int v){
g[u].push_back(v);
g[v].push_back(u);
}
void del(int id){
b[b[id].l].r=b[id].r;
b[b[id].r].l=b[id].l;
b[id].vis=1;
}
void solve(int s){
queue<int> q;q.push(s);
del(s);
while(!q.empty()){
int u=q.front();q.pop();
siz[ans]++;
fu(i,0,(signed)g[u].size()-1)b[g[u][i]].mark=1;
for(int i=b[0].r;i;i=b[i].r)
if(!b[i].vis&&!b[i].mark)q.push(i),del(i);
fu(i,0,(signed)g[u].size()-1)b[g[u][i]].mark=0;
}
}
int main(){
scanf("%d%d",&n,&m);
fu(i,1,m){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
}
b[0].r=1;
fu(i,1,n)b[i].l=i-1,b[i].r=i+1;
b[n].r=0;
fu(i,1,n)if(!b[i].vis)++ans,solve(i);
sort(siz+1,siz+ans+1);
printf("%d\n",ans);
fu(i,1,ans)printf("%d ",siz[i]);
return 0;
}
BZOJ1098 POI2007 办公楼biu 【链表+bfs】的更多相关文章
- 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决 ...
- BZOJ 1098: [POI2007]办公楼biu 链表
求补图连通块,用链表优化,势能O(n+m) #include<cstdio> #include<cstring> #include<iostream> #inclu ...
- bzoj 1098 [POI2007]办公楼biu——链表
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1098 求补图的连通块大小.与自己没有边的和自己在一个连通块里. 用链表把所有点串起来.先给自 ...
- 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
BZOJ_1098_[POI2007]办公楼biu_链表优化BFS Description FGD开办了一家电话公司.他雇用了N个职员,给了每个职员一部手机.每个职员的手机里都存储有一些同事的 电话号 ...
- 【BZOJ】1098: [POI2007]办公楼biu(补图+bfs+链表)
http://www.lydsy.com/JudgeOnline/problem.php?id=1098 显然答案是补图连通块..... 想到用并查集...可是连补图的边都已经...n^2了...怎么 ...
- [BZOJ 1098] [POI2007] 办公楼biu 【链表优化BFS】
题目链接:BZOJ - 1098 题目分析 只有两个点之间有边的时候它们才能在不同的楼内,那么就是说如果两个点之间没有边它们就一定在同一座楼内. 那么要求的就是求原图的补图的连通块. 然而原图的补图的 ...
随机推荐
- ThinkPHP开发笔记-模型
1.模型定义.在ThinkPHP中,可以无需进行任何模型定义.只有在需要封装单独的业务逻辑的时候,模型类才是必须被定义的,因此ThinkPHP在模型上有很多的灵活和方便性,让你无需因为表太多而烦恼. ...
- Memcached CAS 命令
Memcached CAS(Check-And-Set 或 Compare-And-Swap) 命令用于执行一个"检查并设置"的操作 它仅在当前客户端最后一次取值后,该key 对应 ...
- OpenID 和 OAuth 的区别及第三方登录的安全隐患分析
转自:http://itindex.net/detail/48552-openid-oauth-%E6%96%B9%E7%99%BB 发表时间:2014-03-13 19:09 | 作者:天梯梦 出处 ...
- python异常列表
http://www.runoob.com/python/python-exceptions.html https://www.cnblogs.com/zhangyingai/p/7097920.ht ...
- Java栈的两种实现
1. 基于数组 package Algorithm.learn; import java.util.Arrays; /** * Created by liujinhong on 2017/3/7. * ...
- 重新学习MySQL数据库9:Innodb中的事务隔离级别和锁的关系
重新学习MySQL数据库9:Innodb中的事务隔离级别和锁的关系 Innodb中的事务隔离级别和锁的关系 前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁 ...
- centos7 rabbitmq 安装
http://www.rabbitmq.com/install-rpm.html Overview rabbitmq-server is included in Fedora. However, th ...
- PKUSC2013 BUG集锦
如果今年考试真的是这个难度,那比的就是速度和准确度了…… a A:不明觉厉 B:推公式后不明觉厉 C:树的HASH D:不明觉厉 E:QAQ 复制代码'-'忘改'+' WA×1, F:QAQ 请输出 ...
- python3 堆排序
思路: 1.建立堆 2.得到堆顶元素,为最大元素 3.去掉堆顶,将堆最后一个元素放到堆顶,此时可通过一次调整重新使堆有序. 4.堆顶元素为第二大元素. 5.重复步骤3,直到堆变空. 动画 代码: de ...
- LeetCode OJ:Rotate List(旋转链表)
Given a list, rotate the list to the right by k places, where k is non-negative. For example:Given 1 ...