[BZOJ 1015]星球大战
转载请注明出处: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; }