您的位置:首页 > Web前端 > JavaScript

[BZOJ1015][JSOI2008]星球大战starwar(并查集)

2016-03-31 23:50 471 查看

题目描述

传送门

题解

正着拆不好拆,那么反向加。

计数的时候简单判断。

代码

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

const int max_m=2e5+5;
const int max_n=max_m*2;
const int max_k=max_n;
const int max_e=max_m*2;

int n,m,x,y,k,alive;
int tot,point[max_n],next[max_e],v[max_e];
int f[max_n];
int query[max_k],ans[max_k];
bool distroyed[max_n];

inline void addedge(int x,int y){
++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y;
++tot; next[tot]=point[y]; point[y]=tot; v[tot]=x;
}

inline int find(int x){
if (x==f[x]) return x;
f[x]=find(f[x]);
return f[x];
}

inline void merge(int x,int y){
int f1=find(x);
int f2=find(y);
f[f1]=f2;
}

int main(){
//  freopen("input.in","r",stdin);
scanf("%d%d",&n,&m);
for (int i=1;i<=m;++i){
scanf("%d%d",&x,&y);
++x; ++y;
addedge(x,y);
}
scanf("%d",&k);
for (int i=1;i<=k;++i){
scanf("%d",&query[i]);
++query[i];
distroyed[query[i]]=true;
}

alive=n-k;
for (int i=1;i<=n;++i) f[i]=i;

for (int i=1;i<=n;++i)
if (!distroyed[i]){
for (int j=point[i];j;j=next[j])
if (!distroyed[v[j]]&&find(v[j])!=find(i)){
merge(i,v[j]);
--alive;
}
}
ans[k]=alive;

for (int i=k;i>=1;--i){
distroyed[query[i]]=false;
alive++;
for (int j=point[query[i]];j;j=next[j])
if (!distroyed[v[j]]&&find(v[j])!=find(query[i])){
merge(query[i],v[j]);
--alive;
}
ans[i-1]=alive;
}

for (int i=0;i<=k;++i)
printf("%d\n",ans[i]);
}


总结

新的并查集技巧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: