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. codeforces616B

    Dinner with Emma CodeForces - 616B Jack decides to invite Emma out for a dinner. Jack is a modest st ...

  2. windows新增/修改/删除系统环境变量bat示例,一键配置JAVA_HOME

    setx JAVA_HOME "C:\Program Files\java\jdk1.6.0_27" /m setx classpath = ".;%JAVA_HOME% ...

  3. Github提交本地代码

     第一步:建立git仓库 cd到你的本地项目根目录下,执行git命令 git init 第二步:将项目的所有文件添加到仓库中 git add . 如果想添加某个特定的文件,只需把.换成特定的文件名即可 ...

  4. 前端 -- CSS基础

    一,CSS介绍 CSS(Cascading Style Sheet,层叠样式表)定义如何显示HTML元素. 当浏览器读到一个样式表,它就会按照这个样式表来对文档进行格式化(渲染). 二,CSS语法 1 ...

  5. Matplotlib学习---用matplotlib画散点图,气泡图(scatter plot, bubble chart)

    Matplotlib里有两种画散点图的方法,一种是用ax.plot画,一种是用ax.scatter画. 一. 用ax.plot画 ax.plot(x,y,marker="o",co ...

  6. 对strom的理解

    1.什么是strom: storm是一个分布式实时计算系统,用户只需要提供自己的插件(例如一个jar包,其中编写用户自己的逻辑代码),然后将它部署到storm服务器上,storm的master服务器就 ...

  7. Educational Codeforces Round 58 A,B,C,D,E,G

    A. Minimum Integer 链接:http://codeforces.com/contest/1101/problem/A 代码: #include<bits/stdc++.h> ...

  8. MT【288】必要性探路

    已知$f(x)=e^x-\dfrac{1}{2}ax^2-b$(1)当$a=1,b=1$时,求$f(x)$在$[-1,1]$上的值域.(2)若对于任意实数$x$,$f(x)\ge0$恒成立,求$a+b ...

  9. 【QML与C++混合编程】用QVariantList传递数组类型成员

    2017.5.8 更新:Record类要用指针,QObject 不能有拷贝函数. 我有一个C++中自定义的ReaderModel,继承自QAbstractListModel类,传递给了QML. 它的m ...

  10. 洛谷P4581 [BJOI2014]想法(玄学算法,拓扑排序)

    洛谷题目传送门 萝卜大毒瘤 题意可以简化成这样:给一个DAG,求每个点能够从多少个入度为\(0\)的点到达(记为\(k\)). 一个随机做法:给每个入度为\(0\)的点随机一个权值,在DAG上求出每个 ...