http://codeforces.com/problemset/problem/920/E

题意:求一个图的补图的连通分量个数以及每个连通分量里的点个数

如果这不是一个补图,BFS或者并查集可过,但是补图显然是一个稠密图,O(n2)的算法会T,但我们依然可以用BFS来直接跑,但是需要用到链表来进行优化,对于一般的情况而言,开一个vis记录的数组,每次进行O(n)的遍历即可,但是在这一题中,由于在BFS内需要多次遍历可用数组,我们选择用链表来记录所有可用的点,当他们被分配到一个联通块里的时候,入队打标记以及在链表中删除这个点即可。

虽然这是一个稠密图,但是在这样的操作下,事实上每条边的遍历次数和每个点的遍历次数都是十分有限的,时间复杂度可以降低到O(n + m),通过一些细节操作(对vis标记清零的时候不使用memset而是重新遍历清零,查找可用点的时候用链表记录)可以避免队列中产生O(n)的时间复杂度,最终将题目降低到可以接受的时限。

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
const double eps = 1e-;
const int maxn = 2e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,tmp,K;
bool vis[maxn],vis2[maxn];
int head[maxn],tot,pre[maxn],nxt[maxn];
struct Edge{
int to,next;
}edge[maxn * ];
void init(){
Mem(head,); tot = ;
}
VI ans;
void del(int x){
nxt[pre[x]] = nxt[x];
pre[nxt[x]] = pre[x];
}
void add(int u,int v){
edge[++tot].to = v;
edge[tot].next = head[u];
head[u] = tot;
}
int BFS(){
queue<int>Q;
while(nxt[]){
int now = nxt[];
int cnt = ;
del(now);
Q.push(now);
vis2[now] = ;
while(!Q.empty()){
int u = Q.front(); Q.pop();
for(int i = head[u];i;i = edge[i].next) vis[edge[i].to] = ;
for(int i = nxt[];i;i = nxt[i]){
if(!vis[i] && !vis2[i]){
vis2[i] = ;
Q.push(i);
cnt++;
del(i);
}
}
for(int i = head[u];i;i = edge[i].next) vis[edge[i].to] = ;
}
ans.pb(cnt);
}
}
int main()
{
scanf("%d%d",&N,&M);
init();
For(i,,M){
int u,v; scanf("%d%d",&u,&v);
add(u,v); add(v,u);
}
nxt[N] = ;
For(i,,N){
nxt[i - ] = i; pre[i] = i - ;
}
BFS();
sort(ans.begin(),ans.end());
Pri(ans.size());
for(int i = ; i < ans.size(); i ++){
printf("%d ",ans[i]);
}
#ifdef VSCode
system("pause");
#endif
return ;
}

CodeForces920E 链表强优化BFS的更多相关文章

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

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

  2. BZOJ_1098_[POI2007]办公楼biu_链表优化BFS

    BZOJ_1098_[POI2007]办公楼biu_链表优化BFS Description FGD开办了一家电话公司.他雇用了N个职员,给了每个职员一部手机.每个职员的手机里都存储有一些同事的 电话号 ...

  3. HDU 5652 India and China Origins 二分优化+BFS剪枝

    题目大意:给你一个地图0代表可以通过1代表不可以通过.只要能从第一行走到最后一行,那么中国与印度是可以联通的.现在给你q个点,每年风沙会按顺序侵蚀这个点,使改点不可通过.问几年后中国与印度不连通.若一 ...

  4. 2022.7.9 单向链表&数组优化

    相比起数组,链表解决了数组不方便移动,插入,删除元素的弊端,但相应的,链表付出了更加大的内存牺牲换来的这些功能的实现. 链表概述 包含单链表,双链表,循环单链表,实际应用中的功能不同,但实现方式都差不 ...

  5. [HNOI2019]校园旅行(建图优化+bfs)

    30分的O(m^2)做法应该比较容易想到:令f[i][j]表示i->j是否有解,然后把每个路径点数不超过2的有解状态(u,v)加入队列,然后弹出队列时,两点分别向两边搜索边,发现颜色一样时,再修 ...

  6. [原博客] POI系列(2)

    正规.严谨.精妙. -POI bzoj 1098 : [POI2007]办公楼biu 如果把互相有手机号的建边得到一个无向图,那么这个图的补图的连通分量个数就是答案了.因为互相没手机号的必然在同一个连 ...

  7. BFS算法的优化 双向宽度优先搜索

    双向宽度优先搜索 (Bidirectional BFS) 算法适用于如下的场景: 无向图 所有边的长度都为 1 或者长度都一样 同时给出了起点和终点 以上 3 个条件都满足的时候,可以使用双向宽度优先 ...

  8. BFS总结

    能够用 BFS 解决的问题,一定不要用 DFS 去做! 因为用 Recursion 实现的 DFS 可能造成 StackOverflow! (NonRecursion 的 DFS 一来你不会写,二来面 ...

  9. 数据结构与算法JavaScript (三) 链表

    我们可以看到在javascript概念中的队列与栈都是一种特殊的线性表的结构,也是一种比较简单的基于数组的顺序存储结构.由于javascript的解释器针对数组都做了直接的优化,不会存在在很多编程语言 ...

随机推荐

  1. xx.hbm.xml中相关重要的配置

    1.<!-- 指定hibernate操作数据库时的隔离级别             #hibernate.connection.isolation 1|2|4|8                 ...

  2. java基础之Number

    1.Java是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java为每一个基本数据类型都引入了对应的包装类型(wrapper ...

  3. python之旅六【第七篇】面向对象

    面向对象三大特性 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发“更快更好更强... 面向对象编程 ...

  4. BZOJ3133[ballmachine]——倍增+优先队列

    题目描述 有一个装球机器,构造可以看作是一棵树.有下面两种操作: 从根放入一个球,只要下方有空位,球会沿着树滚下.如果同时有多个点可以走,那么会选择编号最小的节点所在路径的方向.比如依次在树根4放2个 ...

  5. Educational Codeforces Round 60 Div. 2

    F:考虑对于每个字母对求出删掉哪些字符集会造成字符串不合法,只要考虑相邻出现的该字母对即可,显然这可以在O(np2)(或小常数O(np3))内求出.然后再对每个字符集判断是否能通过一步删除转移而来即可 ...

  6. mpvue——Error: EPERM: operation not permitted

    报错 $ npm run build > mpvue@ build D:\wamp\www\webpack\mpvue\my-project > node build/build.js w ...

  7. Cetos 7 防火墙设置

    1.关闭防火墙: # systemctl stop firewalld.service 2.开启防火墙: # systemctl start firewalld.service 3.关闭开机启动: # ...

  8. HDU4035 Maze 【树形DP】【期望DP】

    题目分析: 以前一直不会这个方法, 我好菜啊. 转移分为三个部分,一个是直接成功,一个是转移到E1,还有一个是转移到自己周围的一圈儿点. 如果是叶子那么只能转移到父亲,如果不是叶子可以把非叶子的转移代 ...

  9. 前后端分离之vue2.0+webpack2 实战项目 -- html模板拼接

    对于前后端分离,如何把一个页面的公共部分比如head, header, footer, content等组合成一个完整的html 是一个值得考虑的地方. 对于php,我们可以利用include加载其他 ...

  10. 洛谷P3953 逛公园(NOIP2017)(最短/长路,拓扑排序,动态规划)

    洛谷题目传送门 又是一年联赛季.NOIP2017至此收官了. 这个其实是比较套路的图论DP了,但是细节有点恶心. 先求出\(1\)到所有点的最短路\(d1\),和所有点到\(n\)的最短路\(dn\) ...