bzoj1015: [JSOI2008]星球大战starwar
题解:并查集;
发现按顺序拆集合不行,就干脆反过来来合并集合;
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<iomanip> 7 #include<map> 8 #include<set> 9 #include<vector> 10 #include<ctime> 11 #include<cmath> 12 using namespace std; 13 const int maxn=404000; 14 struct node{ 15 int y,next; 16 }e[maxn]; 17 int linkk[maxn],len=0,fa[maxn],vis[maxn],q[maxn],g[maxn]; 18 int n,m,k; 19 void insert(int x,int y){ 20 e[++len].y=y; 21 e[len].next=linkk[x]; 22 linkk[x]=len; 23 } 24 int getfather(int x){ 25 int y=x,temp; 26 while(fa[y]!=y)y=fa[y]; 27 while(y!=x){ 28 temp=fa[x]; 29 fa[x]=y; 30 x=temp; 31 } 32 return y; 33 } 34 bool Union(int x,int y){ 35 x=getfather(x);y=getfather(y); 36 if(x==y)return 0; 37 fa[x]=y;return 1; 38 } 39 void work(){ 40 scanf("%d %d",&n,&m);int x,y; 41 for(int i=1;i<=m;i++){ 42 scanf("%d %d",&x,&y);x++,y++; 43 insert(x,y);insert(y,x); 44 } 45 scanf("%d",&k); 46 for(int i=1;i<=k;i++){scanf("%d",&q[i]);q[i]++;vis[q[i]]=1;} 47 for(int x=1;x<=n;x++){ 48 fa[x]=x; 49 if(vis[x])continue; 50 for(int i=linkk[x];i;i=e[i].next){ 51 if(vis[e[i].y])continue; 52 Union(x,e[i].y); 53 } 54 } 55 int ans=0; 56 for(int i=1;i<=n;i++){ 57 fa[i]=getfather(i); 58 if(fa[i]==i&&!vis[i])ans++; 59 } 60 for(int j=k;j>=1;j--){ 61 x=q[j];vis[x]=0; 62 for(int i=linkk[x];i;i=e[i].next){ 63 if(vis[e[i].y])continue; 64 if(Union(e[i].y,x))ans--; 65 } 66 g[j]=ans; 67 } 68 for(int i=1;i<=k;i++)printf("%d\n",g[i]); 69 } 70 int main(){ 71 work(); 72 return 0; 73 }