题干:

You are given an undirected graph consisting of n vertices and  edges. Instead of giving you the edges that exist in the graph, we give you m unordered pairs (x, y) such that there is no edge between x and y, and if some pair of vertices is not listed in the input, then there is an edge between these vertices.

You have to find the number of connected components in the graph and the size of each component. A connected component is a set of vertices X such that for every two vertices from this set there exists at least one path in the graph connecting these vertices, but adding any other vertex to X violates this rule.

Input

The first line contains two integers n and m (1 ≤ n ≤ 200000, ).

Then m lines follow, each containing a pair of integers x and y (1 ≤ x, y ≤ nx ≠ y) denoting that there is no edge between x and y. Each pair is listed at most once; (x, y) and (y, x) are considered the same (so they are never listed in the same test). If some pair of vertices is not listed in the input, then there exists an edge between those vertices.

Output

Firstly print k — the number of connected components in this graph.

Then print k integers — the sizes of components. You should output these integers in non-descending order.

Example

Input

5 5
1 2
3 4
3 2
4 2
2 5

Output

2
1 4 

题目大意:

无向图中给定n个顶点,m条不存在的边(除了这m条边,其余都存在),求图的连通分量,及每个连通分量的大小。

解题报告:

官方题解:

别从给定的边入手,而是直接对所有顶点bfs就可以了,可以证明复杂度是线性的,顶多加上容器自带的log。

当然, 其实用不到upperbound,因为bfs就是边删除边进行的,不会涉及迭代器危机。但是dfs就比较危险了,下面代码就有对应官方题解的dfs。

AC代码1:(240ms)

vector维护当前还剩多少点没有被访问到(注意巧妙的O1维护方式,正常的维护需要On的时间)。map记录边的信息

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define F first
#define S second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 2e5 + 5;
map<int,bool> mp[MAX];
vector<int> vv,ans;
int bfs(int x) {int res = 0;queue<int> q;q.push(x);while(q.size()) {int cur = q.front();q.pop();res++;
//      int up = vv.size();这里不能这样写,因为size是动态的。for(int i = 0; i<(int)vv.size(); i++) {int v = vv[i];if(mp[cur].count(v) == 0) {swap(vv[i],vv.back());//用来实现set的erase操作,减少常数。 vv.pop_back();//用来实现set的erase操作 i--;q.push(v);}}}return res;
}
int main()
{int n,m;cin>>n>>m;for(int i = 1; i<=n; i++) vv.pb(i);for(int x,y,i = 1; i<=m; i++) {scanf("%d%d",&x,&y);mp[x][y]=1;mp[y][x]=1;}while(!vv.empty()) {int v = vv.back();vv.pop_back();int cnt = bfs(v);ans.push_back(cnt);}sort(ans.begin(),ans.end());printf("%d\n",ans.size());for(int i = 0; i<(int)ans.size(); i++) {printf("%d ",ans[i]);}return 0 ;
}

AC代码2:

用set维护未被访问的点集,bfs中对于每一个点,先一遍操作,同时记录一个vector,然后再更新到set中(删除元素),这样避免了边操作边更新所带来的迭代器的变化,避免了 不好控制 的情况发生。

AC代码3:

用map<int,set<int> > mp  来减小内存。(实际上也无所谓,直接开2e5个set一样的)

注意dfs中,用pair来接受一个map,也就是这里ip其实代表的就是一个pair。

这里也掌握一种姿势:就算是遇到AC代码2那种  set迭代器的问题的时候,第一可以用AC代码2那种处理方式,第二可以改用map:如果需要删除it,那就先将it记录到tmp中,然后删除it,然后再upperbound一下就可以了。

AC代码4:

bitset维护未访问的点集。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#include<bitset>
#define F first
#define S second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 2e5 + 5;
set<int> ss[MAX];
bitset<MAX> bs;
int n,m,ans[MAX],tot;
void dfs(int x) {bs[x] = 0;ans[tot]++;for(int i = bs._Find_first(); i<bs.size(); i = bs._Find_next(i)) {if(ss[x].count(i) == 0) dfs(i);}
}
int main()
{cin>>n>>m;for(int i = 1; i<=n; i++) bs[i] = 1;for(int u,v,i = 1; i<=m; i++) {scanf("%d%d",&u,&v);ss[u].insert(v);ss[v].insert(u);}for(int i = 1; i<=n; i++) {if(bs[i]) tot++,dfs(i);}printf("%d\n",tot);sort(ans+1,ans+tot+1);for(int i = 1; i<=tot; i++) {printf("%d%c",ans[i],i == tot ? '\n' : ' ');}return 0 ;
}

贴一个更快的:

AC代码5:

//别人的代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define F first
#define S second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 2e5 + 5;
set<int>st;
vector<int> mp[MAX];
int ans[MAX];
int del[MAX];
int n,m,tot;
void Bfs(int x) {tot++;ans[tot]=1;st.erase(x);queue<int>s;s.push(x);while(!s.empty()) {int u=s.front();s.pop();int cnt=0;for(set<int>::iterator it=st.begin(); it!=st.end(); it++) {int to=*it;if(binary_search(mp[u].begin(),mp[u].end(),to) == 0) {s.push(to);ans[tot]++;del[++cnt]=to;}}for(int i=1; i<=cnt; i++)st.erase(del[i]);}
}
int main()
{scanf("%d%d",&n,&m);tot=0;st.clear();for(int i=1; i<=m; i++) {int x,y;scanf("%d%d",&x,&y);mp[x].push_back(y);mp[y].push_back(x);}for(int i=1; i<=n; i++)st.insert(i),sort(mp[i].begin(),mp[i].end());for(int i=1; i<=n; i++) {if(st.count(i))Bfs(i);}printf("%d\n",tot);sort(ans+1,ans+tot+1);for(int i=1; i<=tot; i++) {printf("%d ",ans[i]);}
}

【CodeForces - 920E】Connected Components? (dsu,补图连通块,STLset+map,bfs 或bitset)相关推荐

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

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

  2. Educational Codeforces Round 37 (Rated for Div. 2) E. Connected Components? 暴力 + 补图的遍历

    传送门 文章目录 题意: 思路: 题意: n≤2e5,m≤2e5n\le2e5,m\le2e5n≤2e5,m≤2e5. 思路: 这是题是我上个题的一部分,算是个小知识点,暴力能过. 直接维护一个set ...

  3. C. Edgy Trees Codeforces Round #548 (Div. 2) 【连通块】

    一.题面 here 二.分析 这题刚开始没读懂题意,后来明白了,原来就是一个数连通块里点数的问题.首先在建图的时候,只考虑红色路径上的点.为什么呢,因为为了不走红色的快,那么我们可以反着想只走红色的路 ...

  4. 【牛客 - 368D】动态连通块(并查集+bitset优化)

    题干: 小T有n个点,每个点可能是黑色的,可能是白色的. 小T对这张图的定义了白连通块和黑连通块: 白连通块:图中一个点集V,若满足所有点都是白点,并且V中任意两点都可以只经过V中的点互相到达,则称V ...

  5. 1335:【例2-4】连通块——dfs、bfs

    [题目描述] 一个n × m的方格图,一些格子被涂成了黑色,在方格图中被标为1,白色格子标为0.问有多少个四连通的黑色格子连通块.四连通的黑色格子连通块指的是一片由黑色格子组成的区域,其中的每个黑色格 ...

  6. *【ZOJ - 3781】Paint the Grid Reloaded(dfs求连通块缩点,bfs求最短路,建图技巧)

    题干: Leo has a grid with N rows and M columns. All cells are painted with either black or white initi ...

  7. Codeforces 920E-Connected Components? (set,补图,连通块)

    Connected Components? CodeForces - 920E You are given an undirected graph consisting of n vertices a ...

  8. 【Codeforces Round #548(Div. 2)】Edgy Trees(数学+bfs求连通块)

    题目链接 C. Edgy Trees time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  9. connected components algorithm连通组件算法

    connected components algorithm连通图算法 什么是connected components algorithm? 用通俗的话说就是一个图像的前景部分有几部分构成,用下面的这 ...

最新文章

  1. feign调用走不走网关全局拦截_feign服务端出异常客户端处理的方法
  2. django_models_关系一对多
  3. 关于mac的一些常用操作记录
  4. GMIS 2017大会Wesly Mukai演讲:智能运输的未来
  5. 数字图像处理:第五章 代数运算
  6. 一个字符串中到底能有多少个字符? 我竟然算错了!
  7. 12句让人心疼的话 哪一句说到你心里了?
  8. Python基础:文件的操作
  9. 网页版 QQ授权登录
  10. keil、Proteus下载及安装教程
  11. exeScope软件修改exe或dll文件资源-20150818
  12. 毛星云opencv之DrawLine函数写法
  13. 2022最新Postman安装以及基本操作使用教程
  14. 钱诚11.29黄金白银TD美盘走势分析及期货原油操作建议
  15. 密码学大作业(共三次)
  16. Android API 29 百度步行导航语音tts集成
  17. poj1637(混合图判欧拉回路)
  18. Androi开发基础
  19. Blackhat 2017Defcon 25学习笔记
  20. 小程序毕设作品之微信疫苗预约小程序毕业设计(7)中期检查报告

热门文章

  1. asp。net中常用的文件操作类
  2. DotNET内存管理与垃圾回收[转]
  3. 使用SDL打造游戏世界之入门篇 - 7
  4. 801. Minimum Swaps To Make Sequences Increasing
  5. [Leedcode][JAVA][第85题][第221题][最大正方形][动态规划]
  6. [剑指offer]面试题第[2]题[JAVA][替换空格][函数][字符串]
  7. etlgr是什么服务器_ETL是指什么 - 金融行业 - ITPUB论坛-中国专业的IT技术社区
  8. C#中宏定义#define、预处理#if #else #endif的使用
  9. python安装copy_python中copy和deepcopy 的区别
  10. stat函数_数据分析工具入门 掌握这些Excel函数就够了