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 }
View Code

 

posted @ 2018-04-21 09:01  Driver_Lao  阅读(131)  评论(0编辑  收藏  举报