链表加bfs求补图联通块
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求补图联通块的更多相关文章
- 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 ...
- Feeding Time 【bfs求最大连通块】
题目链接:https://ac.nowcoder.com/acm/contest/1870/J 题目大意:求最大的连通块是多大 主要是为了防止自己忘记bfs怎么写..... #include<s ...
- 分别利用并查集,DFS和BFS方法求联通块的数量
联通块是指给定n个点,输入a,b(1<=a,b<=n),然后将a,b连接,凡是连接在一起的所有数就是一个联通块: 题意:第一行输入n,m,分别表示有n个数,有输入m对连接点,以下将要输入m ...
- 图-用DFS求连通块- UVa 1103和用BFS求最短路-UVa816。
这道题目甚长, 代码也是甚长, 但是思路却不是太难.然而有好多代码实现的细节, 确是十分的巧妙. 对代码阅读能力, 代码理解能力, 代码实现能力, 代码实现技巧, DFS方法都大有裨益, 敬请有兴趣者 ...
- 【UVA10765】Doves and bombs (BCC求割点后联通块数量)
题目: 题意: 给了一个联通无向图,现在问去掉某个点,会让图变成几个联通块? 输出的按分出的从多到小,若相等,输出标号从小到大.输出M个. 分析: BCC求割点后联通块数量,Tarjan算法. 联通块 ...
- 【BZOJ 1098】办公楼(补图连通块个数,Bfs)
补图连通块个数这大概是一个套路吧,我之前没有见到过,想了好久都没有想出来QaQ 事实上这个做法本身就是一个朴素算法,但进行巧妙的实现,就可以分析出它的上界不会超过 $O(n + m)$. 接下来介绍一 ...
- 用dfs求联通块(UVa572)
一.题目 输入一个m行n列的字符矩阵,统计字符“@”组成多少个八连块.如果两个字符所在的格子相邻(横.竖.或者对角线方向),就说它们属于同一个八连块. 二.解题思路 和前面的二叉树遍历类似,图也有DF ...
- 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构成的格子,对 ...
- POJ-3107 Godfather 求每个节点连接的联通块数量
dp[n][2],维护儿子的联通块数量和父亲的联通块数量. 第一遍dfs求儿子,第二遍dfs求爸爸. #include<iostream> #include<cstring> ...
随机推荐
- CRMEB系统开发文档
CRMEB系统开发文档 https://gitee.com/ZhongBangKeJi/CRMEB hibernate:学习文档https://blog.csdn.net/u013087513/art ...
- python——Pycharm的简单介绍
一.什么是Pycharm? Pycharm是一种python IDE,带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,比如调试.语法高亮.Project管理.代码跳转.智能提示.自 ...
- Unity中各种格式计时器
问题背景: 在开发游戏过程中,很多地方需要倒计时,但是各种地方要的倒计时格式不同,倒计时都会写,在这里不详细介绍,写的目的就是为了记录一下,方便复用(为了在开发过程中不为了小问题浪费不必要脑细胞) 1 ...
- python-shutil学习
shutil:高级的 文件.文件夹.压缩包 处理模块 1. shutil.copyfileobj(fsrc, fdst[, length])(copyfileobj方法只会拷贝文件内容)将文件内容拷贝 ...
- Emacs中的拼写检查
无论是在Emacs中写英文日记(diary).Org mode笔记,还是撰写程序的注释和文档,拼写检查都是一项提高工作效率.保证成果品质的必不可缺的工具.拼写检查对于常见的文字处理软件(如Word.L ...
- Tomcat7配置Https
使用的是UCloud的免费证书: 教程: https://docs.ucloud.cn/security/ussl/index 购买证书的地址: https://console.ucloud.cn/u ...
- 【redis】在dotnet core下的redis的使用
1.Install-Package Microsoft.Extensions.Caching.Redis -Version 2.2.0 2.注入 services.AddDistributedRedi ...
- C# 0xC0000005 捕获
[HandleProcessCorruptedStateExceptions]//捕获c++异常 [SecurityCritical]//捕获c++异常 public void xxx() { try ...
- MYSQL可调用执行自定义SQL的代码
DELIMITER $$ USE `mysql_wispeed01`$$ DROP PROCEDURE IF EXISTS `sp_execSQL`$$ CREATE DEFINER=`sa`@`%` ...
- 深入理解CPP与C中bsearch函数的用法
·使用besearch函数的前提(一些废话) 首先让我们先亮出二分法的定义: https://baike.baidu.com/item/二分法/1364267 以及二分法实现的方法: https:// ...