Codeforces 292D Connected Components (并查集)
题意 给出一张无向图,每次询问删去第Li--Ri 条边
求此时有多少个连通块
题解
求出一个前缀 Li 表示 加入前 i 条边时图的连通状况
以及一个后缀 Ri 表示 加入后 i 条边时图的连通状况
对于每个询问 删除 s--t 条边
只要将 L s-1 和 R t+1 合并 一下 就行了
合并 其实 就是讲 s-1 和 t+1 对应的 f[ i ] Union 一下就行了
为什么 这就相当于把前缀 i 和 后缀 i 通过一条边相连 ,两个就是连通的了
这样图就合并了
1 #include <bits/stdc++.h> 2 using namespace std ; 3 4 const int N = 511,M = 10011 ; 5 struct bing{ 6 int i,e,f[N] ; 7 void init() 8 { 9 e = 0 ; 10 for(i=0;i<N;i++) f[ i ] = i ; 11 } 12 int find(int x) 13 { 14 if(f[x]==x) return x ; 15 return f[x] = find(f[x]) ; 16 } 17 void Union(int x,int y) 18 { 19 x = find(x) ; 20 y = find(y) ; 21 if(x!=y) f[x] = y,e++ ; 22 } 23 }l[M],r[M]; 24 int n,m,Q,s,t ; 25 int from[M],to[M] ; 26 27 int main() 28 { 29 scanf("%d%d",&n,&m) ; 30 for(int i=1;i<=m;i++) 31 scanf("%d%d",&from[ i ],&to[ i ]) ; 32 l[ 0 ].init() ; r[ m+1 ].init() ; 33 for(int i=1;i<=m;i++) 34 l[ i ] = l[ i-1 ] , l[ i ].Union( from[ i ],to[ i ] ) ; 35 for(int i=m;i>=1;i--) 36 r[ i ] = r[ i+1 ] , r[ i ].Union( from[ i ],to[ i ] ) ; 37 38 scanf("%d",&Q) ; 39 while(Q--) 40 { 41 scanf("%d%d",&s,&t) ; 42 bing tmp = l[s-1] ; 43 for(int i=1;i<=n;i++) tmp.Union( l[ s-1 ].f[ i ],r[ t+1 ].f[ i ] ) ; 44 printf("%d\n",n-tmp.e) ; 45 } 46 47 return 0 ; 48 }
时间: 2024-10-17 07:43:27