题解 CF920E 【Connected Components?】
Mickey_snow · · 题解
CF920E Connected Components? : 链表优化广度优先搜索。
题目大意:给定一张无向图
这里补图就是完全图
我们先将所有的边读入进来,假定一开始所有的点都不属于任何一个连通块,然后将所有的点扫一遍,如果发现一个点
BFS代码如下,我们可以以这个为模型考虑优化的方案。
int _count(const int &start) {
queue<int> que; que.push(start);
vis[start] = true;
int nowAt, _cnt = 1, i;
while (!que.empty()) {
nowAt = que.front(); que.pop();
sort(G[nowAt].begin(), G[nowAt].end());
for (int to = i = 0; to < totPoints; to++) {
if (i < G[nowAt].size() && to == G[nowAt][i]) { i++; continue; }
if (!vis[to]) { vis[to] = true; que.push(to); _cnt++; }
}
}
return _cnt;
}
时间超出限制的根本原因就是枚举
套上了链表,我们还可以用一个集合
AC代码如下:
#include<bits/stdc++.h>
using namespace std;
//链表----------------------------
struct Node {
int val; Node *nxt;
void DeleteNext() {
if (this->nxt == nullptr)return;
Node *it = this->nxt; this->nxt = it->nxt;
it = nullptr;
}
}*frnt = nullptr;
Node* newNode() {
Node* ext = (Node*)malloc(sizeof(Node));
ext->nxt = nullptr; return ext;
}
void build(size_t siz) { //在一开始,所有的点都在链表中
frnt = newNode(); frnt->val = 0;
Node *it = frnt, *ext;
for (int i = 1; i < siz; i++) {
ext = newNode(); ext->val = i;
it->nxt = ext; it = ext;
}
}
//-------------------------------------
#define MAXPOINTS 200005
vector<int> cnt; //每一个连通块包含的点的个数
int totPoints, totEdges;
bool vis[MAXPOINTS];
struct Edge {
int fr, to;
bool operator < (Edge comp) const {
return fr == comp.fr ? to < comp.to : fr < comp.fr;
}
};
set<Edge> G; //图G
int _count(const int &start) {//广搜
queue<int> que; que.push(start);
int nowAt, _cnt = 1;
while (!que.empty()) {
nowAt = que.front(); que.pop();
for (Node *it = frnt; it != nullptr && it->nxt != nullptr;) {//我也不知道这里到底循环了多少次
if (vis[it->nxt->val]) { it->DeleteNext(); continue; }
if (G.count({ nowAt,it->nxt->val }) || it->nxt->val == nowAt) { it = it->nxt; continue; }
vis[it->nxt->val] = true; _cnt++;
que.push(it->nxt->val);
it->DeleteNext();
}
}
return _cnt;
}
int main()
{
memset(vis, false, sizeof(vis));
int a, b;
cin >> totPoints >> totEdges;
for (int i = 0; i < totEdges; i++) {
scanf("%d%d", &a, &b); --a; --b;
G.insert({ a,b }); G.insert({ b,a });
}
build(totPoints);
for (Node* it = frnt; it != nullptr; it = it->nxt) {
if (vis[it->val])continue;
vis[it->val] = true;
cnt.push_back(_count(it->val));
}
cout << cnt.size() << endl;
sort(cnt.begin(), cnt.end());//输出时要是排好序了的
for (const auto &it : cnt)
printf("%d ", it);
putchar('\n');
//system("pause");
return 0;
}
其实,如果去掉链表的部分不看,代码还是非常直观的
有了链表的优化可以将所有枚举将为 O(玄学)