[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]); }
总结
新的并查集技巧。相关文章推荐
- html、javascript、url特殊字符的转义诠释及使用方法详解
- 面向对象在javascript中的实践之多种方式创建对象
- 再看《JavaScript高级程序设计》第13、14、17、20-25章
- JavaScript BOM与客户端检测
- JavaScript中"==, !="和"===, !=="的异同和优劣
- JS脚本收藏(一些实用的函数)
- 有关JSTL核心core标签库的学习
- Prototype in JavaScript
- 通过Ajax方式提交含有文件的表单
- ajax jsonp 跨域
- javaScript简易运动框架封装——和派孔明
- <input type='text'/>如何让获取默认焦点,不用js
- javascript,一幅图让你看懂DIV拖拽
- 1-5-JS基础-数组应用及实例应用
- js 事件监听封装
- JS的事件处理程序
- js实现密码加密
- JS高级程序设置笔记(三)
- JqPagination动态分页,每次点击下一页都加载一次后台
- JS计算时间差