G-Operating on a Graph

题目链接

大致题意

给你一个图,有 个点, 条边,点的下标从
对于点 ,其开始时属于
总共操作 次,每次操作时给出一个 ,将所有与 直接相连的 加入到
在所有操作结束后,求每个点所在的

简单思路方向

利用 STLlist 的连接,list 模拟 queue,然后用并查集做

具体思路

首先, …………这不就是并查集吗…………
只不过其提供的边不可以一下子拿来 unite 只能一层层 unite (从 的角度考虑,这个层的意思)
那么可以为每个 上保存一个 queue ,然后每次使用这个 queue 来进行一层的

但是考虑到两个 联合之后导致其中一个 queue 的数据应该与另外一个合并,而 queue 的合并效率太低,所以使用 list 来模拟 queue,因为 listsplice 方法,效率非常高

其次为了避免重复 ,所以增加了 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;
}