1. 程式人生 > 實用技巧 >DFS_200. 島嶼數量

DFS_200. 島嶼數量

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;
}