链接:
http://codeforces.com/contest/292/problem/D
题意:
给你一个图,n个点,m条边
每次询问l,r 问如果删除第l条边到第r条边之间的所有边,有多少联通分量
题解:
前缀并查集和后缀并查集就可以了
代码:
31 int n, m, k; 32 int x[MAXN], y[MAXN]; 33 int P[MAXN][510]; 34 int rP[MAXN][510]; 35 int PP[510]; 36 int vis[510]; 37 38 int find(int *par,int x) { 39 return par[x] = par[x] == x ? x : find(par, par[x]); 40 } 41 42 void unite(int *par, int x, int y) { 43 int a = find(par, x), b = find(par, y); 44 if (a != b) par[a] = b; 45 } 46 47 int main() { 48 ios::sync_with_stdio(false), cin.tie(0); 49 cin >> n >> m; 50 rep(i, 1, m + 1) cin >> x[i] >> y[i]; 51 rep(i, 1, n + 1) P[0][i] = i; 52 rep(i, 1, m + 1) { 53 rep(j, 1, n + 1) P[i][j] = P[i - 1][j]; 54 unite(P[i], x[i], y[i]); 55 } 56 rep(i, 1, n + 1) rP[m + 1][i] = i; 57 per(i, 1, m + 1) { 58 rep(j, 1, n + 1) rP[i][j] = rP[i + 1][j]; 59 unite(rP[i], x[i], y[i]); 60 } 61 cin >> k; 62 while (k--) { 63 int l, r; 64 cin >> l >> r; 65 rep(i, 1, n + 1) PP[i] = P[l - 1][i]; 66 rep(i, 1, n + 1) unite(PP, i, find(rP[r + 1], i)); 67 memset(vis, 0, sizeof(vis)); 68 int ans = 0; 69 rep(i, 1, n + 1) if (!vis[find(PP, i)]) { 70 ans++; 71 vis[find(PP, i)] = 1; 72 } 73 cout << ans << endl; 74 } 75 return 0; 76 }