题意:给定一个图,点n<=105,边m<=106,现在求它的补图有多少个联通分量。。

思路:很容易想到并查集,但是补图边太多了。。

于是只能优化掉一些多余的边。。

具体做法是用队列优化。。

刚开始把所有没被连接的点用一个链表连接起来,那么选取一个未扩展得点u,就可以吧链表分成两个,一个就是跟他补图有边的,一个是没边的。。

并把有边的跟他连接起来。。删除链表。。并放入队列。。

这样每个点进入队列一次,每条边被访问2次。。时间复杂度为O(n+m)

code:

 #include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<stack>
#include<ctime>
#define repf(i, a, b) for (int i = (a); i <= (b); ++i)
#define repd(i, a, b) for (int i = (a); i >= (b); --i)
#define M0(x) memset(x, 0, sizeof(x))
#define Inf 0x7fffffff
#define MP make_pair
#define PB push_back
#define eps 1e-8
#define pi acos(-1.0)
using namespace std;
const int maxn = ;
const int maxm = ;
struct edge{
int v, next;
} e[maxm];
struct node{
node *x, *y;
} n1[maxn], n2[maxn], *list[], *d[], tr, *null = &tr;
int fa[maxn], last[maxn], tot, n, m; void add(const int& u, const int& v){
e[tot] = (edge){v, last[u]}, last[u] = tot++;
} void init(){
memset(last, -, sizeof(last));
int u, v;
for (int i = ; i < m; ++i){
scanf("%d%d", &u, &v);
add(u, v), add(v, u);
}
} int sz[maxn], inlist[maxn];
int find(int k){
return fa[k] == k ? k : fa[k] = find(fa[k]);
} void delnode(node *it){
it->x->y = it->y, it->y->x = it->x;
it->x = it->y = null;
} void addnode(node *list, node *it){
it->x = list, it->y = list->y;
list->y->x = it, list->y = it;
} void clear(int c){
node *uu;
for (node *it = list[c]; it != null;){
uu = it->y;
it->x = it->y = null;
it = uu;
}
} void solve(){
M0(n1), M0(n2), M0(inlist);
list[] = n1 + n + , list[] = n2 + n + ;
node *it, *uu;
list[]->x = list[]->y = null, list[]->x = list[]->y = null;
d[] = n1, d[] = n2;
int c = , u, v;
for (int i = ; i <= n; ++i) addnode(list[c], d[c] + i), inlist[i] = ;
for (int i = ; i <= n; ++i) fa[i] = i;
queue<int> q;
while (list[c]->y != null){
u = list[c]->y - d[c];
q.push(u);
while (!q.empty()){
int s = c ^ ;
u = q.front(), q.pop();
clear(s);
for (int p = last[u]; ~p; p = e[p].next){
v = e[p].v;
if (!inlist[v]) continue;
delnode(d[c] + v);
addnode(list[s], d[s] + v);
}
int fu = find(u), fv;
for (it = list[c]->y; it != null; it = it->y){
v = it - d[c];
if (!inlist[v]) continue;
fv = find(v);
if (fu != fv) fa[fv] = fu;
inlist[v] = , q.push(v);
}
c = s;
}
}
M0(sz);
for (int i = ; i <= n; ++i)
++sz[find(i)];
vector<int> ans;
for (int i = ; i <= n; ++i) if (sz[i])
ans.push_back(sz[i]);
sort(ans.begin(), ans.end());
printf("%d\n", (int)ans.size());
for (int i = ; i < (int)ans.size(); ++i)
i == ans.size()- ? printf("%d\n", ans[i]) : printf("%d ", ans[i]); } int main(){
// freopen("a.in", "r", stdin);
// freopen("a.out", "w", stdout);
while (scanf("%d%d", &n, &m) != EOF){
init();
solve();
}
return ;
}

[poi2007] biu的更多相关文章

  1. 开始做POI啦...

    库 为了效率搞了这么一个库: 现在版本号1.14(一月十四日更新版本囧..) http://pan.baidu.com/s/1c0SoGfu [source] http://pan.baidu.com ...

  2. BZOJ1098: [POI2007]办公楼biu

    从问题可以看出是求补图的连通块及点数 但补图太大.所以考虑缩小规模. 当一个点归属于一个连通块后,它以后就不需要了.所以可以用链表,删去这个点,也就减小了规模. 一个点开始bfs,每个点只会进队一次, ...

  3. bzoj 1098 [POI2007]办公楼biu bfs+补图+双向链表

    [POI2007]办公楼biu Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 1543  Solved: 743[Submit][Status][Di ...

  4. 5098: [BZOJ1098][POI2007]办公楼biu

    5098: [BZOJ1098][POI2007]办公楼biu 没有数据结构就很棒 一个看上去非常玄学的代码 const int N=1e5+10,M=2e6+10; int n,m; int fa[ ...

  5. 【BZOJ】1098: [POI2007]办公楼biu(补图+bfs+链表)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1098 显然答案是补图连通块..... 想到用并查集...可是连补图的边都已经...n^2了...怎么 ...

  6. [BZOJ 1098] [POI2007] 办公楼biu 【链表优化BFS】

    题目链接:BZOJ - 1098 题目分析 只有两个点之间有边的时候它们才能在不同的楼内,那么就是说如果两个点之间没有边它们就一定在同一座楼内. 那么要求的就是求原图的补图的连通块. 然而原图的补图的 ...

  7. 【链表】Bzoj1098[POI2007]办公楼biu

    Description FGD开办了一家电话公司.他雇用了N个职员,给了每个职员一部手机.每个职员的手机里都存储有一些同事的电话号码.由于FGD的公司规模不断扩大,旧的办公楼已经显得十分狭窄,FGD决 ...

  8. 【刷题】BZOJ 1098 [POI2007]办公楼biu

    Description FGD开办了一家电话公司.他雇用了N个职员,给了每个职员一部手机.每个职员的手机里都存储有一些同事的 电话号码.由于FGD的公司规模不断扩大,旧的办公楼已经显得十分狭窄,FGD ...

  9. 【BZOJ1098】[POI2007]办公楼biu

    题目一开始看以为和强联通分量有关,后来发现是无向边,其实就是求原图的补图的联通块个数和大小.学习了黄学长的代码,利用链表来优化,其实就是枚举每一个人,然后把和他不相连的人都删去放进同一个联通块里,利用 ...

随机推荐

  1. .net妹纸转Java---java环境的搭建,myeclipse10.0 的安装环境变量配置和破解

    啦啦啦 ,因为公司项目需要,从我大火炉--大武汉被拖到了更大的火炉--大广西  其实一开始 我的内心是拒绝的. 但是我在大武汉呆了近2年木有出过远门,对, 生活除了眼前的苟且,还有远方的苟且.怀揣这样 ...

  2. Android布局6大类

    1:在我们Android开发中,常见的布局的方式有6大类 线性布局LinearLayout 相对布局RelativeLayout 表格布局TableLayout 单帧布局FrameLayout 绝对布 ...

  3. python学习之——eclipse+pydev 环境搭建

    最终选用 eclipse+pydev,网上相关资料也是极多的~~~ 1.安装python: 2.安装eclipse: 3.eclipse中安装pydev,eclipse中help—>eclipl ...

  4. python:爬虫

    模块: (1)url管理器:对url进行管理 (2)网页下载器(urllib2):将需要爬取的url指定的网页以字符串的形式下载下来 (3)网页解释器(BeautifulSoup):解析 利用urll ...

  5. 【转】Linux学习之路--启动VNC服务

    我的Linux是Fedora 13,安装方法如下: 1.打开终端,执行 # yum install -y tigervnc tigervnc-server 2.编辑/etc/sysconfi/vncs ...

  6. web测试方法总结

    链接地址:http://www.cnblogs.com/Jessy/p/3539638.html 一.输入框 1.字符型输入框: (1)字符型输入框:英文全角.英文半角.数字.空或者空格.特殊字符“~ ...

  7. sublime配置coffeeScript

    node.js 全局模块所在目录  npm -g ls 1.安装 npm install -g coffee-script 2.sublime安装CoffeeScript sublime语法高亮插件 ...

  8. ubuntu linux mysql 安装 基本操作 命令

    mysql --help #如果有信息证明系统已经安装了mysql mysql -V #查看版本号 netstat -tap|grep mysql #检查mysql是否在启动状态 卸载mysql: s ...

  9. cxf+spring+数字签名开发webservice(二)

    场景         上一章中的webservice接口,因为现场正式环境的项目与外部单位网络不通,是通过前置机与外部进行数据交换,所以我们将webservice部署在前置机,在使用HttpURLCo ...

  10. javascript中关于深复制与浅复制的问题

    在javascript中,变量的类型分为基本类型和引用类型. 对于基本类型的变量来说,值的复制以及作为函数参数实参传递的过程都是值的复制传递,换句话说,是会在内存中开辟出一个新空间用于存放新的值的.这 ...