zoukankan      html  css  js  c++  java
  • 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;
    }
    
    
    
    
  • 相关阅读:
    thinkphp 框架的学习(1) 扩展配置文件
    【7】了解Bootstrap栅格系统基础案例(2)
    【6】了解Bootstrap栅格系统基础案例(1)
    【5】了解Bootstrap预置的栅格系统
    【4】创建一个自己的Bootstrap模板
    【3】Bootstrap的下载和目录结构
    【2】认识Bootstrap
    【1】Bootstrap入门引言
    css(html)背景图优化合并
    CSS2书写顺序
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/13368851.html
Copyright © 2011-2022 走看看