标签:etc define 离线 div oid 倒序 style 题目 names
题目大意:
一个n个点m条边的无向图,现在依次删除k个点及它们的边
求开始有几个联通块及每次删除一个点后的联通块
思路:
直接做不太好做
所以我们可以把删除离线下来
先把不被删的点之间都连起来,联通块个数即为最后一次的输出
然后倒序加入每个被删的点
再倒序输出即可
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstdlib> 6 #include<cstring> 7 #include<queue> 8 #include<map> 9 #include<vector> 10 #define ll long long 11 #define inf 2147483611 12 #define MAXN 400100 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch==‘-‘) f=-1;ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-‘0‘;ch=getchar();} 19 return x*f; 20 } 21 int n,m,nxt[MAXN],to[MAXN],fst[MAXN],f[MAXN],cnt,ans[MAXN],q[MAXN],hsh[MAXN],k; 22 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;} 23 int find(int x) {return x==f[x]?x:f[x]=find(f[x]);} 24 int main() 25 { 26 n=read(),m=read(); 27 int a,b; 28 memset(ans,0xff,sizeof(ans)); 29 for(int i=1;i<=m;i++) {a=read()+1,b=read()+1;add(a,b);add(b,a);} 30 int Q=read(); 31 for(int i=1;i<=Q;i++) q[i]=read()+1,hsh[q[i]]=1; 32 for(int i=1;i<=n;i++) f[i]=i; 33 int num=0; 34 for(int i=1;i<=n;i++) 35 { 36 if(hsh[i]) continue; 37 num++;k=find(i); 38 for(int j=fst[i];j;j=nxt[j]) if(!hsh[to[j]]) if(find(to[j])!=k) f[find(to[j])]=k,num--; 39 } 40 ans[Q+1]=num; 41 while(Q) 42 { 43 num++;k=find(q[Q]); 44 for(int j=fst[q[Q]];j;j=nxt[j]) if(!hsh[to[j]]) if(find(to[j])!=k) f[find(to[j])]=k,num--; 45 hsh[q[Q]]=0; 46 ans[Q]=num;Q--; 47 } 48 for(int i=1;i;i++) {if(ans[i]==-1) break;printf("%d\n",ans[i]);} 49 }
标签:etc define 离线 div oid 倒序 style 题目 names
原文地址:http://www.cnblogs.com/yyc-jack-0920/p/7892189.html