[BZOJ3237][AHOI2013]连通图(分治并查集)

Posted HocRiser

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ3237][AHOI2013]连通图(分治并查集)相关的知识,希望对你有一定的参考价值。

3237: [Ahoi2013]连通图

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 1736  Solved: 655
[Submit][Status][Discuss]

Description

技术分享图片

Input

技术分享图片

Output

技术分享图片

Sample Input

4 5
1 2
2 3
3 4
4 1
2 4
3
1 5
2 2 3
2 1 2

Sample Output



Connected
Disconnected
Connected

HINT

 

 


N<=100000 M<=200000 K<=100000

 

Source

 
[Submit][Status][Discuss]

在线LCT,离线CDQ。

考虑怎么使用CDQ,对于区间[L,R],先将不在[L,mid]而在[mid+1,R]中的边加入,递归到左半边,撤销,将不在[mid+1,R]而在[L,mid]中的边加入,再次递归,撤销。

一般带撤销并查集是不能路径压缩的,但其实压缩了也没关系,记录压缩之前的父亲就好。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define rep(i,l,r) for (int i=l; i<=r; i++)
 5 typedef long long ll;
 6 using namespace std;
 7 
 8 const int N=200100,M=5000100;
 9 struct P{ int u,v,tim; }e[N];
10 struct Q{ int c[5],cnt; }q[N];
11 int top,n,m,T,tim,u,v,f[N],ans[N],stk1[M],stk2[M];
12 
13 int find(int x){
14     if (f[x]==x) return x;
15     int y=find(f[x]);
16     if (y!=f[x]) stk1[++top]=x,stk2[top]=f[x],f[x]=y;
17     return y;
18 }
19 
20 void solve(int l,int r){
21     int Top=top;
22     if (l==r){
23         int flag=1;
24         rep(i,1,q[l].cnt)
25             if (find(e[q[l].c[i]].u)!=find(e[q[l].c[i]].v))
26                 { flag=0; break; }
27         ans[l]=flag;
28         while (top!=Top) f[stk1[top]]=stk2[top],top--;
29         return;
30     }
31     int mid=(l+r)>>1; tim++;
32     rep(i,l,mid) rep(j,1,q[i].cnt) e[q[i].c[j]].tim=tim;
33     rep(i,mid+1,r) rep(j,1,q[i].cnt){
34         int x=q[i].c[j];
35         if (e[x].tim!=tim){
36             int u=find(e[x].u),v=find(e[x].v);
37             if (u!=v) stk1[++top]=u,stk2[top]=f[u],f[u]=v;
38         }
39     }
40     solve(l,mid); tim++;
41     while (top!=Top) f[stk1[top]]=stk2[top],top--;
42     rep(i,mid+1,r) rep(j,1,q[i].cnt) e[q[i].c[j]].tim=tim;
43     rep(i,l,mid) rep(j,1,q[i].cnt){
44         int x=q[i].c[j];
45         if (e[x].tim!=tim){
46             int u=find(e[x].u),v=find(e[x].v);
47             if (u!=v) stk1[++top]=u,stk2[top]=f[u],f[u]=v;
48         }
49     }
50     solve(mid+1,r);
51 }
52 
53 int main(){
54     freopen("bzoj3237.in","r",stdin);
55     freopen("bzoj3237.out","w",stdout);
56     scanf("%d%d",&n,&m); tim=1;
57     rep(i,1,m) scanf("%d%d",&e[i].u,&e[i].v);
58     scanf("%d",&T);
59     rep(i,1,T){
60         scanf("%d",&q[i].cnt); int x;
61         rep(j,1,q[i].cnt) scanf("%d",&x),q[i].c[j]=x,e[x].tim=tim;
62     }
63     rep(i,1,n) f[i]=i;
64     rep(i,1,m) if (e[i].tim!=tim){
65         int u=find(e[i].u),v=find(e[i].v);
66         if (u!=v) f[u]=v;
67     }
68     solve(1,T);
69     rep(i,1,T) if (ans[i]) puts("Connected"); else puts("Disconnected");
70     return 0;
71 }

 

以上是关于[BZOJ3237][AHOI2013]连通图(分治并查集)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3237 [Ahoi2013]连通图

BZOJ3237: [Ahoi2013]连通图

3237: [Ahoi2013]连通图 线段树分治

随机算法瞎练BZOJ3237&3563&3569三倍经验题

BZOJ3236:[AHOI2013]作业——题解

[BZOJ1969][AHOI2005]LANE 航线规划