【2020牛客多校】2020牛客暑期多校训练营(第三场)G-Operating on a Graph——傻逼暴力题

G-Operating on a Graph

题目链接

大致题意

给你一个图,有 n n n 个点, m m m 条边,点的下标从 0 → n − 1 0 \rightarrow n - 1 0n1
对于点 i i i ,其开始时属于 i − g r o u p i-group igroup
总共操作 q q q 次,每次操作时给出一个 n n n ,将所有与 n − g r o u p n-group ngroup 直接相连的 g r o u p group group 加入到 n − g r o u p n-group ngroup
在所有操作结束后,求每个点所在的 g r o u p group group

简单思路方向

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

具体思路

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

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

其次为了避免重复 B F S BFS 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;
}

猜你喜欢

转载自blog.csdn.net/m0_43448982/article/details/107432046