BZOJ 4579 [Usaco2016 Open]Closing the Farm
【题意概述】
给你N点M边的无向图(1<=N,M<=200000),一共删n次点,
每次询问删这个点之前是否完全联通。
【题解】
离线处理询问。倒着做就变成了加边加点,判断是否只有一个联通块。加入每个点now的时候先把cnt加1,然后遍历这个点连出去的边,发现to已经加入并且与now不在一个联通块里,就把它们合并一下,在更新cnt,用并查集维护连通性即可。
1 #include<cstdio> 2 #include<algorithm> 3 #define rg register 4 #define N 200010 5 using namespace std; 6 int n,m,tot,last[N],fa[N],cnt,a[N],ans[N]; 7 bool v[N]; 8 struct edge{ 9 int to,pre; 10 }e[N<<1]; 11 inline int read(){ 12 int k=0,f=1; char c=getchar(); 13 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 14 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 15 return k*f; 16 } 17 inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);} 18 int main(){ 19 n=read(); m=read(); 20 for(rg int i=1;i<=m;i++){ 21 int u=read(),v=read(); 22 e[++tot]=(edge){v,last[u]}; last[u]=tot; 23 e[++tot]=(edge){u,last[v]}; last[v]=tot; 24 } 25 for(rg int i=1;i<=n;i++) a[i]=read(); 26 for(rg int i=1;i<=n;i++) fa[i]=i; 27 for(rg int j=n;j;j--){ 28 cnt++; int now=a[j]; v[now]=1; 29 for(rg int i=last[now],to;i;i=e[i].pre)if(v[to=e[i].to]){ 30 if(find(to)!=find(now)){ 31 cnt--; 32 fa[find(to)]=find(now); 33 } 34 } 35 ans[j]=cnt; 36 } 37 for(rg int i=1;i<=n;i++) puts(ans[i]==1?"YES":"NO"); 38 return 0; 39 }