链表加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> ...
随机推荐
- 20175226 2018-2019-2 《Java程序设计》第六周学习总结
20175226 2018-2019-2 <Java程序设计>第六周学习总结 教材学习内容总结 内部类与异常类 内部类:Java支持在一个类中定义另一个类(可以是static类) 外嵌类的 ...
- ad9361自测试校准
#include "config.h" #include "CONFIG_FPGA_ALL.h" #include "xparameters.h&qu ...
- Git初始配置和基本使用
初次运行Git前的配置 本文是在安裝完git以后首先应做到一些配置,安装教程可以参考廖雪峰git教程 用户信息 当安装完 Git 应该做的第一件事就是设置你的用户名称与邮件地址. 这样做很重要,因为每 ...
- spring5.0.2.RELEASE源码环境构建
Spring5 源码下载注意事项 首先你的JDK 需要升级到1.8 以上.Spring3.0 开始,Spring 源码采用github 托管,不再提供官网下载链接.大家可自行去github 网站下载, ...
- Scyther-Semantics and verification of Security Protocol
1 .本书前一节主要是介作者自己的生平经历(读完感觉作者是个神童),目标明确作者13岁代码已经写的很溜了.自己也开了网络公司,但是后面又专注于自己的计算机基础理论,修了哲学的博士学位(不得不说很多专业 ...
- Gradle 同步时报错,Could not find com.android.support.constraint:constraint-layout:1.0.0-alpha8的解决方法
Error:Could not find com.android.support.constraint:constraint-layout:1.0.0-alpha8. 原因: SDK 中可能是没有安装 ...
- IntelliJ IDEA 如何设置类头注释和方法注释
从VS转过来的,ide的差距很大的,所以...特意折腾了很久,结果还是没有VS的 '///' 好用 一.类头注释 打开file -> setting -> Editor -> Fil ...
- Web开发疑难问题解决方案-(最近更新:2018-11-29)
这篇文章用来记录Web(包括PC和移动端)开发过程中遇到的一些疑难问题的解决方案. P1. '1像素边框'问题 P2.只读输入框在ios上的莫名表现 P3.自适应高度的textarea P4. CSS ...
- Codeforces 1070J Streets and Avenues in Berhattan dp
Streets and Avenues in Berhattan 我们首先能发现在最优情况下最多只有一种颜色会分别在行和列, 因为你把式子写出来是个二次函数, 在两端取极值. 然后我们就枚举哪个颜色会 ...
- python基础知识练习题(一)
1.执行Python脚本的两种方式:WIN+R,cmd,命令行窗口输入:python 进入python模式输入命令行直接执行命令:编写以.py结尾的文件,写入命令行,然后运行python.exe打开 ...