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\n",#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\n", findx(n) - 1);
    }
    return 0;
}



posted @ 2020-07-23 21:28  EchoZQN  阅读(124)  评论(0编辑  收藏  举报