您的位置:首页 > 其它

Educational Codeforces Round 37 E. Connected Components? 链表+bfs

2018-02-04 23:52 393 查看
首先感谢qls群里 提思路,佩服

题意:

给定n个点;m条说明:那两个点之间没边;

问 有多少个连通块,每个的大小按非递减顺序输出;

思路:

很容易想到根据没连边,找到边,然后对点进行dfs,找到连通块标记出来就是了,但是复杂度行不通;

这个过程中,复杂度高的地方是每次要便利所有的数看是否有边;

后来借鉴qls想法,先对所有的点建立链表,然后每次bfs把某个连通块的点拿出来,

因为没连的边的最多有2e5条,所以链表的大小会减少的很快,复杂度也就降了下来;

#include<iostream>
#include<algorithm>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<queue>
#include<list>
#include<stack>
#include<map>
#pragma comment(linker, "/STACK:102400000,102400000")
#define PI acos(-1.0)
#define in freopen("in.txt", "r", stdin)
#define out freopen("out.txt", "w", stdout)
#define kuaidian ios::sync_with_stdio(0);

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 2e5 + 7, maxd = 1e5 + 7;
const int mod = 1e9 + 7;
const int INF = 0x7f7f7f7f;

int n, m;
list<int> lis;
vector<int> vec[maxn], ans;
bool vis1[maxn], vis2[maxn];

void init() {
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; ++i)
lis.push_back(i);
for(int i = 0; i < m; ++i) {
int u, v;
scanf("%d %d", &u, &v);
vec[u].push_back(v);
vec[v].push_back(u);
}
}

int bfs(int id) {
int res = 0;
queue<int> qu;
qu.push(id);
while(!qu.empty()) {
int u = qu.front(); qu.pop();
if(vis1[u]) continue;
vis1[u] = 1; res++;

for(auto &v : vec[u]) vis2[v] = 1;
for(auto i = lis.begin(); i != lis.end(); ) {
int v = *i;
if(vis2[v]) {
i++;
continue;
}
qu.push(v);
lis.erase(i++);
}
for(auto &v : vec[u]) vis2[v] = 0;
}
return res;
}

void solve() {
for(int i = 1; i <= n; ++i) {
if(vis1[i]) continue;
ans.push_back(bfs(i));
}
sort(ans.begin(), ans.end());
printf("%d\n", ans.size());
for(int i = 0; i < ans.size(); ++i) {
printf("%d ", ans[i]);
}
}

int main() {
init();
solve();
return 0;
}

/*
5 5
1 2
3 4
3 2
4 2
2 5
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: