bzoj1015:[JSOI2008]星球大战starwar

思路:反着做用并查集维护连通块个数就好了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 400005

int n,m,tot,k,num;
int now[maxn],pre[maxn],son[maxn],deg[maxn],fa[maxn],ans[maxn];
bool vis[maxn];

inline int read(){
	int x=0;char ch=getchar();
	for (;ch<'0'||ch>'9';ch=getchar());
	for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
	return x;
}

void add(int a,int b){
	son[++tot]=b;
	pre[tot]=now[a];
	now[a]=tot;
}

void link(int a,int b){
	add(a,b),add(b,a);
}

int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}

int main(){
	n=read(),m=read();
	for (int i=1;i<=n;i++) fa[i]=i;
	for (int i=1,a,b;i<=m;i++) a=read(),b=read(),link(a+1,b+1);
	k=read();
	for (int i=1;i<=k;i++) deg[i]=read(),vis[++deg[i]]=1;
	for (int i=1;i<=n;i++)
		if (!vis[i]){
			num++;
			for (int p=now[i];p;p=pre[p])
				if (!vis[son[p]]){
					int u=find(i),v=find(son[p]);
					if (u!=v) fa[u]=v,num--;
				}
		}
	ans[k+1]=num;
	for (int i=k;i;i--){
		num++;
		for (int p=now[deg[i]];p;p=pre[p])
			if (!vis[son[p]]){
				int u=find(deg[i]),v=find(son[p]);
				if (u!=v) fa[u]=v,num--;
			}
		ans[i]=num,vis[deg[i]]=0;
	}
	for (int i=1;i<=k+1;i++) printf("%d\n",ans[i]);
	return 0;
}

 

posted @ 2016-10-30 16:26  DUXT  阅读(...)  评论(...编辑  收藏