BZOJ1015: [JSOI2008]星球大战starwar 并查集 离线处理
2016-07-28 22:47
519 查看
题目大意:
给出一些点和一些边,每次删掉一个点和其连接的边
求每次删除一个点后图中的连通块个数
可以倒过来做并查集。
先按照输入建好一个虚拟的图
再把最后存在的星球之间的边连起来用并查集求出连通块个数
然后按照被攻击星球的逆序不断向图里加入点和边(加入的边的to[i]一定是图中存在的点),每一次用并查集更新连通块个数
按照顺序输出答案
给出一些点和一些边,每次删掉一个点和其连接的边
求每次删除一个点后图中的连通块个数
可以倒过来做并查集。
先按照输入建好一个虚拟的图
再把最后存在的星球之间的边连起来用并查集求出连通块个数
然后按照被攻击星球的逆序不断向图里加入点和边(加入的边的to[i]一定是图中存在的点),每一次用并查集更新连通块个数
按照顺序输出答案
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=400005; int n,m,Q; int D ,da ,ans; bool b ,used ; int cnt,to ,nxt ,lj ; void add(int f,int t) { to[++cnt]=t; nxt[cnt]=lj[f]; lj[f]=cnt; } int fa ; int find(int x) { if(fa[x]==x) return x; fa[x]=find(fa[x]); return fa[x]; } void insert(int x) { int a=find(x); for(int i=lj[x];i;i=nxt[i]) if(used[to[i]]==true)//若to[i]在图中 { int c=find(to[i]); if(a!=c) fa[c]=a,ans--; } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) fa[i]=i; int x,y; for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); x++,y++; add(x,y),add(y,x); } scanf("%d",&Q); for(int i=1;i<=Q;i++)//离线 { scanf("%d",&D[i]); D[i]++; b[D[i]]=true; } for(int i=1;i<=n;i++)//用最后存在的星球建图 if(b[i]==false) { ans++; insert(i); used[i]=true; } da[Q+1]=ans; for(int i=Q;i>=1;i--)//逆序加入被攻击的星球 { ans++; insert(D[i]); used[D[i]]=true; da[i]=ans; } for(int i=1;i<=Q+1;i++) printf("%d\n",da[i]); }
相关文章推荐
- 1611:The Suspects
- 作业四,1001
- 作业四1002
- 作业四1003
- 练习四1005
- 最小权值和
- HDU-1213-How Many Tables
- Longest Consecutive Sequence,Distinct Subsequences,Interleaving String,Scramble String
- 并查集_POJ 1182_食物链
- SARS病毒传染 并查集
- HDU 1213
- CSU1307 并查集+SPFA
- BZOJ3275 Number (最小割)
- BZOJ2809——[Apio2012]dispatching
- BZOJ2809——[Apio2012]dispatching
- 并查集
- BestWiring——Kruskal算法&并查集
- 1611:The Suspects
- 并查集示例1
- 并查集(union-find)学习报告