G-Operating on a Graph
大致题意
给你一个图,有 个点, 条边,点的下标从
对于点 ,其开始时属于
总共操作 次,每次操作时给出一个 ,将所有与 直接相连的 加入到 中
在所有操作结束后,求每个点所在的
简单思路方向
利用 STL
的 list
的连接,list
模拟 queue
,然后用并查集做
具体思路
首先, …………这不就是并查集吗…………
只不过其提供的边不可以一下子拿来 unite
只能一层层 unite
(从 的角度考虑,这个层的意思)
那么可以为每个 上保存一个 queue
,然后每次使用这个 queue
来进行一层的
但是考虑到两个 联合之后导致其中一个 的 queue
的数据应该与另外一个合并,而 queue
的合并效率太低,所以使用 list
来模拟 queue
,因为 list
有 splice
方法,效率非常高
其次为了避免重复 ,所以增加了 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; }