http://acm.hdu.edu.cn/showproblem.php?pid=4496
题意:
给出n个顶点m条边的图,每次选择一条边删去,求每次删边后的连通块个数。
思路:
离线处理删边,从后往前处理变成加边,用并查集维护连通块个数。其实这题和BZOJ 1015差不多。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 6 int n, m, tot, num; 7 int p[10005], ans[100005], head[10005]; 8 9 struct node 10 { 11 int u,v; 12 }query[100005]; 13 14 struct edge 15 { 16 int v,next; 17 }e[200010]; 18 19 void addEdge(int u, int v) 20 { 21 e[tot].v = v; 22 e[tot].next = head[u]; 23 head[u] = tot++; 24 } 25 26 int finds(int x) 27 { 28 return p[x]==x?x:p[x]=finds(p[x]); 29 } 30 31 void update(int u) 32 { 33 for(int i=head[u];i!=-1;i=e[i].next) 34 { 35 int v = e[i].v; 36 int x = finds(u); 37 int y = finds(v); 38 if(x!=y) {p[x]=y;num--;} 39 } 40 } 41 42 int main() 43 { 44 //freopen("in.txt","r",stdin); 45 while(~scanf("%d%d",&n,&m)) 46 { 47 tot = 0; 48 memset(head,-1,sizeof(head)); 49 for(int i=0;i<n;i++) p[i]=i; 50 for(int i=1;i<=m;i++) 51 scanf("%d%d",&query[i].u,&query[i].v); 52 53 num = n; 54 ans[m] = n; 55 for(int i=m;i>0;i--) 56 { 57 int u = query[i].u; 58 int v = query[i].v; 59 addEdge(u,v); 60 addEdge(v,u); 61 update(u); 62 update(v); 63 ans[i-1]=num; 64 } 65 for(int i=1;i<=m;i++) printf("%d ",ans[i]); 66 } 67 return 0; 68 }