bzoj 1015 [JSOI2008]星球大战starwar
Posted huangchenyan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 1015 [JSOI2008]星球大战starwar相关的知识,希望对你有一定的参考价值。
并查集
题目中是说将节点一个个摧毁,正着做并不好做
所以考虑在所有的星球摧毁后反着进行连边
在恢复一个节点后,则恢复了这个节点到之前已恢复的节点的连边,然后用并查集维护联通块即可
注意在同一个联通块中连边是不会改变联通块的个数的
所以只要处理联通块之间的边即可
#include <bits/stdc++.h> using namespace std; const int MAXN=4*1e5+100; int n,m,k,fa[MAXN],q[MAXN],color[MAXN]; int now,nf[MAXN],vi[MAXN]; vector <int> e[MAXN],ans; int find(int x)//并查集 if (fa[x]==x) return fa[x]; fa[x]=find(fa[x]); return fa[x]; void dfs(int x,int now) color[x]=now; for (int i=0;i<(int)e[x].size();i++) if (color[e[x][i]]) continue; dfs(e[x][i],now); int main() scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) int u,v; scanf("%d%d",&u,&v); e[u].push_back(v); e[v].push_back(u); scanf("%d",&k); for (int i=1;i<=k;i++) scanf("%d",&q[i]); vi[q[i]]=1; int co=0; for (int i=0;i<n;i++) if (color[i]) continue; co++; dfs(i,co); //对残余的图进行染色,判断联通块 printf("%d\n",co); for (int i=0;i<n;i++) fa[i]=i; for (int i=0;i<n;i++) if (vi[i]) continue; for (int j=0;j<(int)e[i].size();j++) if (vi[e[i][j]]) continue; if (find(e[i][j])!=find(i)) fa[find(i)]=find(e[i][j]); for (int i=0;i<n;i++) if (vi[i]) continue; if (nf[find(i)]==0) now++; nf[find(i)]=1; for (int i=k;i>=1;i--) ans.push_back(now); int u; u=q[i]; vi[u]=0; for (int j=0;j<(int)e[u].size();j++) if (vi[e[u][j]]) continue; int v; v=e[u][j];//进行加边 if (find(u)!=find(v)) if (nf[find(u)]==1 && nf[find(v)]==1) nf[find(u)]=0; now--; fa[find(u)]=find(v); if (nf[find(u)]==0) nf[find(u)]=1; now++; for (int i=(int)ans.size()-1;i>=0;i--) printf("%d\n",ans[i]);
以上是关于bzoj 1015 [JSOI2008]星球大战starwar的主要内容,如果未能解决你的问题,请参考以下文章
bzoj1015 [JSOI2008]星球大战starwar
bzoj 1015: [JSOI2008]星球大战starwar
BZOJ1015[JSOI2008]星球大战starwar[并查集]
BZOJ-1015: [JSOI2008]星球大战starwar (并查集)