bzoj 1015 并查集,离线
题意:n个点,m条双向边,k个询问。每次删掉一个点,问连通块个数。
tags:一开始按顺序做,发现搞不出来。。离线做,从后往前,把删除变为添加。
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a;i<=b;i++) #define per(i,b,a) for (int i=b;i>=a;i--) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f typedef long long ll; const int N = 4e5+10; struct Edge{int to, next;}e[N<<1]; int n, m, k, fa[N], head[N], ans[N], q[N], tot, sum; bool flag[N]; void Addedge(int u, int v) {e[++tot].to=v, e[tot].next=head[u], head[u]=tot;} int Find(int x) {return x==fa[x] ? x : fa[x]=Find(fa[x]);} void add(int u) { flag[u]=0, sum++; for(int i=head[u]; i; i=e[i].next) { int v=e[i].to; if(flag[v]==0) { int fau=Find(u), fav=Find(v); if(fau!=fav) fa[fav]=fau, sum--; } } } int main() { scanf("%d %d", &n, &m); rep(i,0,n-1) fa[i]=i; int u, v; rep(i,1,m) { scanf("%d %d", &u, &v); Addedge(u, v); Addedge(v, u); } scanf("%d", &k); rep(i,1,k) scanf("%d", &q[i]), flag[q[i]]=1; rep(i,0,n-1) if(flag[i]==0) add(i); ans[k+1]=sum; per(i,k,1) add(q[i]), ans[i]=sum; rep(i,1,k+1) printf("%d\n", ans[i]); return 0; }