Description
你应该知道无向图的连通块的数量,你应该知道如何求连通块的数量。当你兴奋与你的成就时,破坏王Alice拆掉了图中的边。当她发现,每删去一条边,你都会记下边的编号,同时告诉她当前连通块的个数。
然而,对边编号简直就是个悲剧,因为Alice为了刁难你,拆掉编号从l到r的边,当然你需要做的事情就是求连通块的个数。如果你答对了,Alice会把拆掉的边装好,迚行下一次破坏。如果你无法完成这个任务,Alice会彻底毁了你的图。
进行完足够多次之后,Alice觉得无聊,就玩去了,而你却需要继续做第三题。
Input
第一行两个整数n,m,表示点数和边数。
之后m行每行两个整数x,y,表示x与y之间有无向边。(按读入顺序给边编号,编号从1开始)
一行一个整数k,表示Alice的破坏次数。
之后k行,每行两个整数l,r。
Output
k行,每行一个整数。
Sample Input
6 5
1 2
5 4
2 3
3 1
3 6
6
1 3
2 5
1 5
5 5
2 4
3 3
Sample Output
4
5
6
3
4
2
Data Constraint
对于30%的数据,n<=100,k<=10
对于60%的数据,k<=1000
对于100%的数据,n<=500,m<=10000,k<=20000,1<=l<=r<=m
Solution
connect:并查集。每一个f[i]为一个并查集,记录只添加前i条边时,所有节点的联通情况。每一个g[i]也是一个并查集,记录只添加i—m条边时,所有节点的联通情况。对于每个询问只要把f[l-1]和g[r+1]合并即可。
合并只需判断f中i的祖先是否和g中i的祖先在h(h为合并的数组)中联通,如果不连通则将他们连起来。
Code1
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 520
#define M 10010
using namespace std;
int n,m,k,l,r,ans=0,f[M][N],g[M][N],x[M],y[M],h[M];
int getf(int x,int k){
if(f[k][x]==x) return x;
return f[k][x]=getf(f[k][x],k);
}
int getg(int x,int k){
if(g[k][x]==x) return x;
return g[k][x]=getg(g[k][x],k);
}
int geth(int x){
if(h[x]==x) return x;
return h[x]=geth(h[x]);
}
int main(){
freopen("connect.in","r",stdin);
freopen("connect.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) f[0][i]=g[m+1][i]=i;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++) f[i][j]=f[i-1][j];
scanf("%d%d",&x[i],&y[i]);
int fx=getf(x[i],i),fy=getf(y[i],i);
if(fx!=fy) f[i][fx]=f[i][fy];
}
for(int i=m;i>=1;i--){
for(int j=1;j<=n;j++) g[i][j]=g[i+1][j];
int fx=getg(x[i],i),fy=getg(y[i],i);
if(fx!=fy) g[i][fx]=g[i][fy];
}
scanf("%d",&k);
for(int i=1;i<=k;i++){
scanf("%d%d",&l,&r);
for(int j=1;j<=n;j++) h[j]=f[l-1][j];
for(int j=1;j<=n;j++){
int fx=geth(j),fy=geth(getg(j,r+1));
if(fx!=fy) h[fx]=fy;
}
ans=0;
for(int j=1;j<=n;j++) if(h[j]==j) ans++;
printf("%d\n",ans);
}
return 0;
}
Code2
#pragma GCC optimize(3)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<list>
#include<queue>
#include<stack>
#include<bitset>
#include<deque>
using namespace std;
#define ll long long
#define ri register int
#define il inline
#define fi first
#define se second
#define mp make_pair
#define pi pair<int,int>
#define mem0(x) memset((x),0,sizeof (x))
#define mem1(x) memset((x),0x3f,sizeof (x))
il char gc() {
static const int BS = 1 << 22;
static unsigned char buf[BS], *st, *ed;
if (st == ed) ed = buf + fread(st = buf, 1, BS, stdin);
return st == ed ? EOF : *st++;
}
#define gc getchar
template<class T>void in(T &x) {
x = 0;
bool f = 0;
char c = gc();
while (c < '0' || c > '9') {
if (c == '-') f = 1;
c = gc();
}
while ('0' <= c && c <= '9') {
x = (x << 3) + (x << 1) + (c ^ 48);
c = gc();
}
if (f) x = -x;
}
#undef gc
#define pb push_back
#define N 510
#define M 20010
int v[M], u[M];
int n, m;
int find(int x, int k[]) {
return k[x] == x ? x : k[x] = find(k[x], k);
}
int f[10002][502], cntf;
int mpf[10002];
int g[10003][502], cntg;
int mpg[10002];
map< pi, int>rem;
int tmp[502];
signed main() {
#ifndef ONLINE_JUDGE
#endif
freopen("connect.in", "r", stdin);
freopen("connect.out", "w", stdout);
in(n), in(m);
for (ri i = 1, a, b; i <= m; ++i) {
in(a), in(b);
u[i] = a, v[i] = b;
}
for (ri i = 1; i <= n; ++i) g[0][i] = f[0][i] = i;
g[0][0] = f[0][0] = n;
for (ri i = 1, fx, fy; i <= m; ++i) {
fx = find(u[i], f[cntf]), fy = find(v[i], f[cntf]);
if (fx == fy) {
mpf[i] = cntf;
continue;
}
++cntf;
for (ri j = 1, lst = cntf - 1; j <= n; ++j) f[cntf][j] = f[lst][j];
f[cntf][fy] = fx;
f[cntf][0] = f[cntf - 1][0] - 1;
mpf[i] = cntf;
}
for (ri i = m, fx, fy; i >= 1; --i) {
fx = find(u[i], g[cntg]), fy = find(v[i], g[cntg]);
if (fx == fy) {
mpg[i] = cntg;
continue;
}
++cntg;
for (ri j = 1, lst = cntg - 1; j <= n; ++j) g[cntg][j] = g[lst][j];
g[cntg][fy] = fx;
g[cntg][0] = g[cntg - 1][0] - 1;
mpg[i] = cntg;
}
int q, l, r, lst, ans, tag;
in(q);
while (q--) {
in(l), in(r);
if (rem.count(mp(mpf[l - 1], mpg[r + 1]))) {
printf("%d\n", rem[mp(mpf[l - 1], mpg[r + 1])]);
continue;
}
if (r == m) {
printf("%d\n", f[mpf[l - 1]][0]);
continue;
}
if (l == 1) {
printf("%d\n", g[mpg[r + 1]][0]);
continue;
}
tag = mpf[l - 1];
lst = mpg[r + 1];
ans = f[tag][0];
for (ri i = 1; i <= n; ++i) tmp[i] = f[tag][i];
for (ri i = 1, fx, tx, ty; i <= n; ++i) {
fx = find(i, g[lst]);
if (fx != i) {
tx = find(i, tmp), ty = find(fx, tmp);
if (tx != ty) {
tmp[ty] = tx;
--ans;
}
}
}
rem[mp(tag, lst)] = ans;
printf("%d\n", ans);
}
return 0;
}
作者:zsjzliziyang
QQ:1634151125
转载及修改请注明
本文地址:https://blog.csdn.net/zsjzliziyang/article/details/81807721