DFS_200. 島嶼數量
阿新 • • 發佈:2020-07-23
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; }