• 2020牛客暑期多校训练营(第三场)G Operating on a Graph


    2020牛客暑期多校训练营(第三场)G Operating on a Graph

    题解:

    对于每一个节点,首先用并查集维护每一个节点属于哪一个组,然后再并节点,这个节点并起来可以用链式前向星来模拟,因为链式前向星是把一个点的所有的边记录变成一条链,所以并掉的点的临近节点就可以用前向星直接连起来,然后这个点把他周围的点并掉之后,他所连的边就是一些新的边了。

    但是要注意的是,可能对于一个点,和他最近的x个点都连向同一个点,所以这个点就会和操作的点连很多次,这样就会 (tle)

    #include <bits/stdc++.h>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    #define debug(x) printf("debug:%s=%lld
    ",#x,x);
    //#define debug(x) cout << #x << ": " << x << endl
    using namespace std;
    const int maxn = 8e5+10;
    typedef long long ll;
    int to[maxn<<1],head[maxn],nxt[maxn<<1],ed[maxn],cnt;
    void add(int u,int v) {
        ++cnt, to[cnt] = v, nxt[cnt] = head[u], head[u] = cnt;
        if (!ed[u]) ed[u] = cnt;
        ++cnt, to[cnt] = u, nxt[cnt] = head[v], head[v] = cnt;
        if (!ed[v]) ed[v] = cnt;
    }
    int f[maxn];
    void init(int n) {
        cnt = 0;
        for (int i = 0; i <= n; i++) head[i] = ed[i] = 0, f[i] = i;
    }
    int findx(int x) {
        return x == f[x] ? x : f[x] = findx(f[x]);
    }
    void unite(int x,int y) {
        x = findx(x);
        y = findx(y);
        if (x == y) return ;
        f[y] = x;
    }
    int num[maxn];
    int main() {
        int t;
        scanf("%d", &t);
        while (t--) {
            int n, m;
            scanf("%d%d", &n, &m);
            init(n);
            for (int i = 1; i <= m; i++) {
                int u, v;
                scanf("%d%d", &u, &v);
                add(u + 1, v + 1);
            }
            int q;
            scanf("%d", &q);
            while (q--) {
                int x, now = 0;
                scanf("%d", &x);
                x++;
                if (x != findx(x)) continue;
                for (int i = head[x]; i; i = nxt[i]) {
                    int v = to[i], fv = findx(v);
                    if(x == fv) continue;
                    num[++now]=fv;
                    unite(x,fv);
                }
                head[x]=0;
                for (int i = 1; i <= now; i++) {
                    int v = num[i];
                    if (!head[v]) continue;
                    if (i == 1) head[x] = head[v], ed[x] = ed[v];
                    else nxt[ed[x]] = head[v], ed[x] = ed[v];
                    head[v] = 0;
                }
            }
            for (int i = 1; i < n; i++) printf("%d ", findx(i) - 1);
            printf("%d
    ", findx(n) - 1);
        }
        return 0;
    }
    
    
    
    
  • 相关阅读:
    JS系列:三元运算符与循环
    浏览器解析js和type判断数据类型
    JS系列:数据类型详细讲解
    JS系列:编程语言
    京东校招面试汇总
    有关axios的request与response拦截
    正则表达式 判断内容是否为合法的url
    H5 小代码(实时更新)
    H5 回到顶部按钮
    图片压缩(js压缩,底部有vue压缩图片依赖使用的教程链接)
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/13368143.html
Copyright © 2020-2023  润新知