[BZOJ 1015]星球大战

danihao123 posted @ 2016年1月30日 13:59 in 题解 with tags BZOJ JSOI 省选 并查集 离线处理 , 607 阅读
转载请注明出处:http://danihao123.is-programmer.com/

这道题到现在才A……

其实……离线处理并不像我想的那样变态……

需要注意的是,离线处理过程中,在将被删除的点加入时,联通分量数可能增加(其他一个点都连不了)

代码:

/**************************************************************
    Problem: 1015
    User: danihao123
    Language: C++
    Result: Accepted
    Time:1688 ms
    Memory:15620 kb
****************************************************************/
 
#include <cstdio>
#include <stack>
#include <cctype>
#include <vector>
using namespace std;
const int maxn=400000;
// 图
vector<int> G[maxn];
inline void Add_Edge(int x,int y){
    G[x].push_back(y);
}
// 并查集
int p[maxn],rank[maxn];
int find_set(int x){
    if(p[x]==x)
        return x;
    else
        return p[x]=find_set(p[x]);
}
inline void link(int x,int y){
    if(rank[x]>rank[y]){
        p[y]=x;
    }else{
        p[x]=y;
        if(rank[x]==rank[y])
            rank[y]++;
    }
}
void merge_set(int x,int y){
    link(find_set(x),find_set(y));
}
bool is_same(int x,int y){
    return find_set(x)==find_set(y);
}
inline void init_set(int n){
    for(register int i=0;i<n;i++)
        p[i]=i;
}
// I/O优化
inline int readint(){
    char c=getchar();
    register int x=0;
    while(!isdigit(c))
        c=getchar();
    while(isdigit(c)){
        x=x*10+c-'0';
        c=getchar();
    }
    return x;
}
int bf[10];
inline void writeint(int x){
    register int p=0;
    if(x==0){
        bf[p++]=0;
    }else{
        while(x){
            bf[p++]=x%10;
            x/=10;
        }
    }
    for(register int i=p-1;i>=0;i--)
        putchar('0'+bf[i]);
}
stack<int> ans_stk;
bool vis[maxn];
int cut[maxn];
int main(){
    register int i,j,ans,u,v;
    int n,m,k;
    n=readint();
    m=readint();
    for(i=0;i<m;i++){
        u=readint();
        v=readint();
        Add_Edge(u,v);
        Add_Edge(v,u);
    }
    k=readint();
    ans=n-k;
    for(i=0;i<k;i++){
        cut[i]=readint();
        vis[cut[i]]=true;
    }
    init_set(n);
    for(i=0;i<n;i++)
        if(!vis[i]){
            for(j=0;j<G[i].size();j++){
                v=G[i][j];
                if(!vis[v] && !is_same(i,v)){
                    merge_set(i,v);
                    ans--;
                }
            }
        }
    ans_stk.push(ans);
    for(i=k-1;i>=0;i--){
        u=cut[i];
        vis[u]=false;
        ans++;
        for(j=0;j<G[u].size();j++){
            v=G[u][j];
            if(!vis[v] && !is_same(u,v)){
                merge_set(u,v);
                ans--;
            }
        }
        ans_stk.push(ans);
    }
    while(!ans_stk.empty()){
        u=ans_stk.top();
        ans_stk.pop();
        writeint(u);
        putchar('\n');
    }
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter