https://oj.neu.edu.cn/problem/1387

给一个点数N <= 100000, 边 <= 1000000的无向图,求补图的联通块数,以及每个块包含的点数

由于点数太大,补图会是稠密图,甚至建立补图都要O(n^2),只能挖掘一下联通块,bfs,补图的性质,从原图入手求补图的联通块:

在原图中不直接相邻的点,在补图中一定属于同一个联通块

每个点只属于一个联通块,所以找好一个联通块之后可以删去这个联通块的所有点,把图规模缩小

这样子:1.准备一个集合放所有未探索的点,初始化时将1~N放进去

2.从集合中取一点放入队列(新的联通块)

3.当队列不为空时,从队列中取一个点u并弹出,将原图中与u直接相连的点标记;遍历集合,将在集合中的(即未探索的)并且未被标记的点(这些点属于本联通块)入队并从集合中删去,将标记删去。重复执行直到队列为空

4.集合不为空转2,为空结束

考虑有删除操作和时间问题,集合的实现当然是选择链表,用数组实现的双向链表即可 

优化有两个:一是通过原图找补图的联通块;二是把搜过的点删除,这样每次找未标记的点时比起从1循环到N更优(常数优化(误))

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int maxn = 1e5+, maxm = 1e6+, inf = 0x3f3f3f3f;
struct lnk{
int val;
int pre, nxt;
}lk[maxn];
struct edge{
int v, nxt;
}e[maxm*];
int head[maxn], tot, block_cnt, n, m;
int adj[maxn], vis[maxn], num[maxn];
void addedge(int u, int v){
e[tot] = (edge){v, head[u]};
head[u] = tot++;
}
void dele(int x){
lk[lk[x].nxt].pre = lk[x].pre;
lk[lk[x].pre].nxt = lk[x].nxt;
}
void src(){
for(int i = ; i <= n; i++){
vis[i] = adj[i] = ;
}
queue<int>Q;
block_cnt = ;
while(lk[].nxt != -){
//puts("blk++");
Q.push(lk[].nxt);
//printf("take %d\n", lk[0].nxt);
vis[lk[lk[].nxt].val] = ;
dele(lk[].nxt);
block_cnt++;
num[block_cnt] = ;
while(!Q.empty()){
int x = Q.front();
x = lk[x].val;
//printf("%d\n", x);
Q.pop();
for(int i = head[x]; ~i; i = e[i].nxt){
int v = e[i].v;
adj[v] = ;
}
for(int i = lk[].nxt; ~i; i = lk[i].nxt){
int w = lk[i].val;
if(!vis[w] && !adj[w]){
Q.push(w);
vis[w] = ;
dele(i);
num[block_cnt]++;
}
}
for(int i = head[x]; ~i; i = e[i].nxt){
int v = e[i].v;
adj[v] = ;
}
}
}
}
int main(){
int t;
scanf("%d", &t);
while(t--){
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++)
head[i] = -;
tot = ;
while(m--){
int u, v;
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
}
for(int i = ; i <= n; i++){
lk[i].val = i;
lk[i].pre = i-;
lk[i].nxt = i+;
}
lk[n].nxt = -;
lk[].nxt = ;
src();
sort(num+, num+block_cnt+);
printf("%d\n", block_cnt);
for(int i = ; i <= block_cnt; i++){
printf("%d%c", num[i], i == block_cnt ? '\n' : ' ');
}
}
return ;
}
/*
3
5 7
1 2
1 3
1 4
1 5
2 3
2 4
2 5
6 9
1 4 1 5 1 6
2 4 2 5 2 6
3 4 3 5 3 6
3 3
1 2 2 3 3 1 */

链表加bfs求补图联通块的更多相关文章

  1. Codeforces Round #369 (Div. 2) D. Directed Roads dfs求某个联通块的在环上的点的数量

    D. Directed Roads   ZS the Coder and Chris the Baboon has explored Udayland for quite some time. The ...

  2. Feeding Time 【bfs求最大连通块】

    题目链接:https://ac.nowcoder.com/acm/contest/1870/J 题目大意:求最大的连通块是多大 主要是为了防止自己忘记bfs怎么写..... #include<s ...

  3. 分别利用并查集,DFS和BFS方法求联通块的数量

    联通块是指给定n个点,输入a,b(1<=a,b<=n),然后将a,b连接,凡是连接在一起的所有数就是一个联通块: 题意:第一行输入n,m,分别表示有n个数,有输入m对连接点,以下将要输入m ...

  4. 图-用DFS求连通块- UVa 1103和用BFS求最短路-UVa816。

    这道题目甚长, 代码也是甚长, 但是思路却不是太难.然而有好多代码实现的细节, 确是十分的巧妙. 对代码阅读能力, 代码理解能力, 代码实现能力, 代码实现技巧, DFS方法都大有裨益, 敬请有兴趣者 ...

  5. 【UVA10765】Doves and bombs (BCC求割点后联通块数量)

    题目: 题意: 给了一个联通无向图,现在问去掉某个点,会让图变成几个联通块? 输出的按分出的从多到小,若相等,输出标号从小到大.输出M个. 分析: BCC求割点后联通块数量,Tarjan算法. 联通块 ...

  6. 【BZOJ 1098】办公楼(补图连通块个数,Bfs)

    补图连通块个数这大概是一个套路吧,我之前没有见到过,想了好久都没有想出来QaQ 事实上这个做法本身就是一个朴素算法,但进行巧妙的实现,就可以分析出它的上界不会超过 $O(n + m)$. 接下来介绍一 ...

  7. 用dfs求联通块(UVa572)

    一.题目 输入一个m行n列的字符矩阵,统计字符“@”组成多少个八连块.如果两个字符所在的格子相邻(横.竖.或者对角线方向),就说它们属于同一个八连块. 二.解题思路 和前面的二叉树遍历类似,图也有DF ...

  8. 2014 Super Training #4 E Paint the Grid Reloaded --联通块缩点+BFS

    原题: ZOJ 3781 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3781 题意: 给一个n*m的X,O构成的格子,对 ...

  9. POJ-3107 Godfather 求每个节点连接的联通块数量

    dp[n][2],维护儿子的联通块数量和父亲的联通块数量. 第一遍dfs求儿子,第二遍dfs求爸爸. #include<iostream> #include<cstring> ...

随机推荐

  1. IntelliJ IDEA设置svn.exe的路径

    安装TortoiseSVN客户端时,必须选中command line client tools这个选项

  2. fastjson与net.sf.json区别

    在现在的开发当中,绝大多数引用阿里巴巴的fastjson.当然net.sf.json同样可以使用. 一.引入net.sf.json包 首先用net.sf.json包,当然你要导入很多包来支持commo ...

  3. JAVA BigDecimal 用法

    一.BigDecimal 的加减乘除 BigDecimal bignum1 = new BigDecimal("10"); BigDecimal bignum2 = new Big ...

  4. RabbitMQ 使用QOS(服务质量)+Ack机制解决内存崩溃的情况

    当消息有几万条或者几十万条的时候,如果消费的方式不对,会造成内存崩溃的情况 一:consumer 1. 短链接:basicget 独自去获取message... request 的方式去获取,断开式. ...

  5. Hadoop HDFS安装、环境配置

    hadoop安装 进入Xftp将hadoop-2.7.3.tar.gz 复制到自己的虚拟机系统下的放软件的地方,我的是/soft/software 在虚拟机系统装软件文件里,进行解压缩并重命名 进入p ...

  6. fastdfsDemo

    package com.xpl.fastdfs; import org.csource.common.NameValuePair;import org.csource.fastdfs.*;import ...

  7. 欧朋Opera 浏览器(打不开百度)提示“您的连接不是私密连接”,解决办法

    它网页报错SSL.提示“您的连接不是私密连接” 打开opera://net-internals/#hsts,操作如下图片,三步以后,ok 如果是其他外国浏览器,用这个办法也有效,可以把前面的 oper ...

  8. 二、OpenStack—keystone组件介绍与安装

    一.Keystone介绍 keystone 是OpenStack的组件之一,用于为OpenStack家族中的其它组件成员提供统一的认证服务,包括身份验证.令牌的发放和校验.服务列表.用户权限的定义等等 ...

  9. 【nuget】PackageReference

    .net 爬虫 <PackageReference Include="HtmlAgilityPack" Version="1.9.0" /> < ...

  10. block学习二:使用Block替代回调

    使用Block替代回调,分为三步进行: