【2020牛客多校】2020牛客暑期多校训练营(第三场)G-Operating on a Graph——傻逼暴力题
G-Operating on a Graph
大致题意
给你一个图,有 \(n\) 个点,\(m\) 条边,点的下标从 \(0 \rightarrow n - 1\)
对于点 \(i\) ,其开始时属于 \(i-group\)
总共操作 \(q\) 次,每次操作时给出一个 \(n\) ,将所有与 \(n-group\) 直接相连的 \(group\) 加入到 \(n-group\) 中
在所有操作结束后,求每个点所在的 \(group\)
简单思路方向
利用 STL
的 list
的连接,list
模拟 queue
,然后用并查集做
具体思路
首先,\(group\) …………这不就是并查集吗…………
只不过其提供的边不可以一下子拿来 unite
只能一层层 unite
(从 \(BFS\) 的角度考虑,这个层的意思)
那么可以为每个 \(group\) 上保存一个 queue
,然后每次使用这个 queue
来进行一层的 \(BFS\)
但是考虑到两个 \(group\) 联合之后导致其中一个 \(group\) 的 queue
的数据应该与另外一个合并,而 queue
的合并效率太低,所以使用 list
来模拟 queue
,因为 list
有 splice
方法,效率非常高
其次为了避免重复 \(BFS\) ,所以增加了 visit
数组
AC code
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 8e5 + 100;
int f[MAXN];
list<int> lists[MAXN];
bool visit[MAXN];
vector<int> node[MAXN];
int finds(int x) {
return x == f[x] ? x : f[x] = finds(f[x]);
}
void unite(int x, int y) {
int rx = finds(x);
int ry = finds(y);
if (rx != ry) {
f[rx] = ry;
lists[ry].splice(lists[ry].end(), lists[rx]);
}
}
void init(int b, int e) { // 初始化函数,范围为 [b, e)
for (int i = b; i < e; i++)
f[i] = i;
}
void bfs(int cur) {
if (finds(cur) != cur) return;
int size = lists[cur].size();
for (int i = 0; i < size; ++i) {
auto explorer = lists[cur].front();
for (auto item : node[explorer]) {
unite(item, cur);
if (visit[item]) continue;
lists[cur].push_back(item);
visit[item] = true;
}
lists[cur].pop_front();
}
}
void solve() {
int T;
cin >> T;
for (int ts = 0; ts < T; ++ts) {
int n, m;
cin >> n >> m;
memset(visit, false, sizeof(bool) * (n + 5));
init(0, n + 5);
for (int i = 0; i < n + 5; ++i) {
node[i].clear();
lists[i].clear();
lists[i].push_back(i);
}
int u, v;
for (int i = 0; i < m; ++i) {
cin >> u >> v;
node[u].push_back(v);
node[v].push_back(u);
}
int q;
cin >> q;
for (int i = 0; i < q; ++i) {
cin >> u;
bfs(u);
}
for (int i = 0; i < n; ++i)
cout << finds(i) << " \n"[i == n - 1];
}
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
#ifdef ACM_LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
int test_index_for_debug = 1;
char acm_local_for_debug;
while (cin >> acm_local_for_debug) {
if (acm_local_for_debug == '$') exit(0);
cin.putback(acm_local_for_debug);
if (test_index_for_debug > 20) {
throw runtime_error("Check the stdin!!!");
}
auto start_clock_for_debug = clock();
solve();
auto end_clock_for_debug = clock();
cout << "Test " << test_index_for_debug << " successful" << endl;
cerr << "Test " << test_index_for_debug++ << " Run Time: "
<< double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
cout << "--------------------------------------------------" << endl;
}
#else
solve();
#endif
return 0;
}