1. 程式人生 > >bzoj 1015 [JSOI2008]星球大戰starwar

bzoj 1015 [JSOI2008]星球大戰starwar

連通塊 turn pri ans 所有 bsp ret pac sca

逆向考慮,先看作所有星球都被摧毀,然後恢復星球。

連通塊個數用並查集維護,每次恢復不能算被毀掉的星球

#include<cstdio>
#include<vector>
using namespace std;
int n,m,k,fa[400001],x,y;
vector<int> G[400001];
int ans[400001];
bool d[400001];
int v[400001];
bool vis[400001];
int gf(int x){
    if(fa[x]==x) return x;
    return fa[x]=gf(fa[x]);
}
int main(){
    scanf(
"%d%d",&n,&m); for(int i=0;i<n;i++) fa[i]=i; for(int i=1;i<=m;i++){ scanf("%d%d",&x,&y); G[x].push_back(y); G[y].push_back(x); } scanf("%d",&k); int now=n; for(int i=1;i<=k;i++){ scanf("%d",&v[i]); d[v[i]]
=1; } for(int i=0;i<n;i++){ if(!d[i]){ vis[i]=1; for(int j=0;j<G[i].size();j++){ if(gf(i)!=gf(G[i][j])&&!d[G[i][j]]){ now--; fa[gf(G[i][j])]=gf(i); } } } } ans[k
+1]=now-k; for(int i=k;i>=1;i--){ ans[i]=ans[i+1]+1;vis[v[i]]=1; for(int j=0;j<G[v[i]].size();j++){ if(gf(v[i])!=gf(G[v[i]][j])&&vis[G[v[i]][j]]){ ans[i]--; fa[gf(G[v[i]][j])]=gf(v[i]); } } } for(int i=1;i<=k+1;i++)printf("%d\n",ans[i]); return 0; }

bzoj 1015 [JSOI2008]星球大戰starwar