bzoj 1015 并查集

 

代码:

//这题可以反着想,把要去掉的点倒着处理变成往图中一个一个的加点,然后用并查集处理联通快就好了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int MAXN=400000;
int fa[MAXN+10],des[MAXN+10],ans[MAXN+10],head[MAXN+10],n,m,k,tot;
bool use[MAXN+10];
struct Edge
{
    int to,next;
}edge[MAXN*2+10];
void init()
{
    tot=0;
    for(int i=0;i<n;i++){
        fa[i]=i;
        use[i]=1;
        head[i]=-1;
    }
}
void add(int x,int y)
{
    edge[tot].to=y;
    edge[tot].next=head[x];
    head[x]=tot++;
}
int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
int main()
{
    scanf("%d%d",&n,&m);
    init();
    for(int i=1;i<=m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    scanf("%d",&k);
    for(int i=1;i<=k;i++){
        scanf("%d",&des[i]);
        use[des[i]]=0;
    }
    int tmp=0;
    for(int i=0;i<n;i++){
        if(!use[i]) continue;
        tmp++;
        for(int j=head[i];j!=-1;j=edge[j].next){
            int x=edge[j].to;
            if(!use[x]) continue;
            int ii=find(i),xx=find(x);
            if(ii!=xx){
                fa[ii]=xx;
                tmp--;
            }
        }
    }
    ans[k]=tmp;
    for(int i=k;i>=1;i--){
        int x=des[i];
        use[x]=1;
        tmp++;
        for(int j=head[x];j!=-1;j=edge[j].next){
            int y=edge[j].to;
            if(!use[y]) continue;
            int xx=find(x),yy=find(y);
            if(xx!=yy){
                fa[xx]=yy;
                tmp--;
            }
        }
        ans[i-1]=tmp;
    }
    for(int i=0;i<=k;i++)
        printf("%d\n",ans[i]);
    return 0;
}

 

posted @ 2017-08-28 21:26  butflfe  阅读(...)  评论(...编辑  收藏