bzoj1015: [JSOI2008]星球大战starwar
很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系。某一天,凭着一个偶然的
机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球。这些星球通过特殊的以太隧道互相直
接或间接地连接。 但好景不长,很快帝国又重新造出了他的超级武器。凭借这超级武器的力量,帝国开始有计划
地摧毁反抗军占领的星球。由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来。现在,反抗军首
领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的星球顺序,以尽量快的速度求出每
一次打击之后反抗军占据的星球的连通快的个数。(如果两个星球可以通过现存的以太通道直接或间接地连通,则
这两个星球在同一个连通块中)。
输入文件第一行包含两个整数,N (1 < = N < = 2M) 和M (1 < = M < = 200,000),分别表示星球的
数目和以太隧道的数目。星球用 0 ~ N-1的整数编号。接下来的M行,每行包括两个整数X, Y,其中(0 < = X <>
Y 表示星球x和星球y之间有“以太”隧道,可以直接通讯。接下来的一行为一个整数k,表示将遭受攻击的星球的
数目。接下来的k行,每行有一个整数,按照顺序列出了帝国军的攻击目标。这k个数互不相同,且都在0到n-1的范
围内。第一行是开始时星球的连通块个数。接下来的K行,每行一个整数,表示经过该次打击后现存星球
的连通块个数。
很明显的并查集,删边不好搞,反向加边即可,用了一个map维护ban掉的点,结果t了,发现不用map直接数组即可
/************************************************************** Problem: 1015 User: walfy Language: C++ Result: Accepted Time:2180 ms Memory:16844 kb ****************************************************************/ //#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack-protector") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") //#pragma GCC optimize("unroll-loops") #include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pi acos(-1.0) #define ll long long #define mod 1000000007 #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pli pair<ll,int> #define pii pair<int,int> #define cd complex<double> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double g=10.0,eps=1e-12; const int N=400000+10,maxn=8000000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; int fa[N],a[N],ans[N]; bool ban[N]; int ma[N]; vector<int>v[N]; int Find(int x) { return fa[x]==x?x:fa[x]=Find(fa[x]); } int main() { int n,m; scanf("%d%d",&n,&m); for(int i=0;i<n;i++)fa[i]=i; int res=n; while(m--) { int a,b;scanf("%d%d",&a,&b); v[a].pb(b);v[b].pb(a); } int k;scanf("%d",&k); for(int i=1;i<=k;i++) { scanf("%d",&a[i]); ban[a[i]]=1; ma[a[i]]=i; } for(int i=0;i<n;i++) { if(ban[i]) { res--; continue; } for(int j=0;j<v[i].size();j++) { if(ban[v[i][j]])continue; int fx=Find(i),fy=Find(v[i][j]); if(fx!=fy)fa[fx]=fy,res--; } } // printf("%d\n",res); ans[k]=res; for(int i=k;i>=1;i--) { for(int j=0;j<v[a[i]].size();j++) { if(ban[v[a[i]][j]]&&ma[v[a[i]][j]]<i)continue; int fx=Find(a[i]),fy=Find(v[a[i]][j]); if(fx!=fy)fa[fx]=fy,res--; } res++; ans[i-1]=res; } for(int i=0;i<=k;i++)printf("%d ",ans[i]); puts(""); return 0; } /******************** 8 13 0 1 1 6 6 5 5 0 0 6 1 2 2 3 3 4 4 5 7 1 7 2 7 6 3 6 5 1 6 3 5 7 ********************/