有向图的连通性用强连通,无向图的连通性用并查集,起码90%的题都可以这么做。
但是这题是不停的删边,并查集根本忍不了啊。
那就倒过来弄呗~一点一点加边存答案,再从头输出
#include <cstdio>
#include <cstring>
#define N 440000
#define M 220000
struct EDGE {
int to, next;
}edge[2*M];
bool flag[N];
int head[N], q[N], fa[N], ans[N];
int n, m, cnt, K;
inline void add(int x, int y) {
edge[++cnt].to = y;
edge[cnt].next = head[x]; head[x] = cnt;
return ;
}
inline int getfa(int x) {
int r = x;
while(r != fa[r]) r = fa[r];
while(x != fa[x]) {int temp = x; x = fa[x]; fa[temp] = r;}
return r;
}
int main() {
freopen("1015.in", "r", stdin);
scanf("%d%d", &n, &m);
memset(head, 0, sizeof(head)); cnt = 0;
for(int i = 1; i <= m; ++i) {
int x, y; scanf("%d%d", &x, &y);
add(x, y); add(y, x);
}
memset(flag, false, sizeof(flag));
scanf("%d", &K);
for(int i = 1; i <= K; ++i) scanf("%d", q+i), flag[q[i]] = true;
int num = n - K;
for(int i = 0; i < n; ++i) fa[i] = i;
for(int i = 0; i < n; ++i)
if(!flag[i]) {
for(int j = head[i]; j; j = edge[j].next) {
int y = edge[j].to;
if(!flag[y]) {
int fax = getfa(i), fay = getfa(y);
if(fax != fay) fa[fay] = fax, --num;
}
}
}
ans[K] = num;
for(int i = K; i > 0; --i) {
int x = q[i]; flag[x] = false; ++num;
for(int j = head[x]; j; j = edge[j].next) {
int y = edge[j].to;
if(!flag[y]) {
int fax = getfa(x), fay = getfa(y);
if(fax != fay) fa[fay] = fax, --num;
}
}
ans[i - 1] = num;
}
for(int i = 0; i <= K; ++i) printf("%d\n", ans[i]);
return 0;
}