这两天复习下基础算法.并查集忘得差不多,开了个专题:http://acm.hust.edu.cn:8080/judge/contest/view.action?cid=12105#overview 密码zisu123
本题的题意是:给出一张无向图,然后依次删除一些边,问每次删边后图中有几个连通分量,简单的并查集..
/* Problem ID:F - Anansi's Cobweb meaning: Analyzing:并查集, */ #include <iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<vector> using namespace std; typedef struct even{int pi,di;}even; #define FOR(i,s,t) for(int i=(s); i<(t); i++) #define LL long #define BUG puts("here!!!") #define print(x) printf("%d\n",x) #define STOP system("pause") #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define maxn 100006 LL gcd(LL a,LL b) {return a?gcd(b%a,a):b;} int num[maxn],pre[maxn],fa,del[maxn],ans[maxn]; even A[maxn]; int flag[maxn]; int T,N,Q,M; void init(){ for(int i=0;i<maxn;i++) pre[i]=-1; memset(flag,0,sizeof(flag)); memset(ans,0,sizeof(ans)); } int find(int x){ int s,tmp; for(s=x;pre[s]>=0;s=pre[s]); while(s!=x){ tmp=pre[x]; pre[x]=s; x=tmp; } return s; } void Union(int R1,int R2){ int r1=find(R1); int r2=find(R2); if(r1==r2) return ; if(pre[r1]>pre[r2]){ pre[r2]+=pre[r1]; pre[r1]=r2; } else { pre[r1]+=pre[r2]; pre[r2]=r1; } } int main(){ while(~scanf("%d%d",&N,&M)){ for(int i=1;i<=M;i++){ scanf("%d%d",&A[i].pi,&A[i].di); } scanf("%d",&Q); int k=0; init(); for(int i=0;i<Q;i++){ scanf("%d",&del[i]); flag[del[i]]=1; } int link=N; for(int i=1;i<=M;i++){ if(flag[i]==0){ if(find(A[i].pi)!=find(A[i].di)) link--; Union(A[i].pi,A[i].di); } } // printf("link %d\n",link); ans[k++]=link; for(int i=Q-1;i>=0;i--){ if(find(A[del[i]].pi)!=find(A[del[i]].di)) link--; Union(A[del[i]].pi,A[del[i]].di); ans[k++]=link; } printf("%d",ans[Q-1]); for(int i=Q-2;i>=0;i--){ printf(" %d",ans[i]); } puts(""); } return 0; }