[BZOJ] 1015 [JSOI2008]星球大战starwar

 

并查集只能合并节点,所以,时光倒流

学到了,统计联通块不用O(n)扫,添加节点+1,合并节点-1。

 

#include<iostream>
#include<cstdio>
#include<stack>
using namespace std;

const int MAXN=400005;

int n,m,q;
int num;
bool ocp[MAXN];
stack<int> que;
stack<int> ans;

int fa[MAXN];
int fnd(int x){
    return x==fa[x]?x:fa[x]=fnd(fa[x]);
}
void cat(int x,int y){
    x=fnd(x);y=fnd(y);
    if(x!=y) {
        fa[y]=x;
        num--;
    }
}

struct Edge{
    int next,to;
}e[MAXN];
int ecnt=1,head[MAXN];
void add(int x,int y){
    e[++ecnt].next = head[x];
    e[ecnt].to = y;
    head[x]=ecnt;
}
void updata(int x){
    num++;
    for(int i=head[x];i;i=e[i].next){
        int v=e[i].to ;
        if(ocp[v]) continue;
        cat(x,v);
    }
}

int query(){
    return num;
}

int main(){
    cin>>n>>m;
    int x,y;
    for(int i=1;i<=m;i++){
//      cin>>x>>y;
        scanf("%d%d",&x,&y);
        x++;y++;
        add(x,y);
        add(y,x);
    }
    cin>>q;
    for(int i=1;i<=q;i++){
//      cin>>x;
        scanf("%d",&x);
        x++;
        ocp[x]=1;
        que.push(x); 
    }
    for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=1;i<=n;i++){
        if(ocp[i]) continue;
        updata(i);
    }
    ans.push(query()); 
    while(!que.empty()){
        int top=que.top() ;
        que.pop() ;
        ocp[top]=0;
        updata(top);
        ans.push(query()); 
    }
    while(!ans.empty()){
//      cout<<ans.top()<<endl;
        printf("%d\n",ans.top());
        ans.pop() ;
    }
    return 0;
}

 

posted @ 2018-07-24 22:57  GhostCai  阅读(101)  评论(0编辑  收藏  举报