[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; }
本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9363217.html