zoukankan      html  css  js  c++  java
  • [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 }
  • 相关阅读:
    放假期间网站被挂马的解决办法
    放假期间网站被挂马的解决办法
    判断一个字符串中字母的个数(无视大小写)
    判断一个字符串中字母的个数(无视大小写)
    JSP 9 大内置对象详解
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    2019年企业数据生产力调研报告,90%的人都没看过
    2019年12月数据库流行度排行:前三甲高位收官 数据库重获增长趋势
  • 原文地址:https://www.cnblogs.com/HocRiser/p/8983151.html
Copyright © 2011-2022 走看看