zoukankan      html  css  js  c++  java
  • bzoj3237 [Ahoi2013]连通图

    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

    正解:$CDQ$分治+并查集。

    我来学习一波$CDQ$图分治。。其实很简单,我们只要在分治$[l,r]$的时候连上$[l,r]$都有的边就行了。

    当$l=r$的时候判断一下那$4$个不连的边对应的点是否连通就行了。

    复杂度为什么是对的呢?我们注意到一条边一定是覆盖了一个区间,而分治的时候区间不超过$logn$个,于是每条边最多只会被连$logn$次。复杂度就是$O(mlogn)$的。

    但是我们还要用并查集,且并查集必须支持撤回,于是我们开个栈记录一下被覆盖掉的父子关系就行了,然后复杂度变成了$O(mlog^{2}n)$。

     1 //It is made by wfj_2048~
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <cstring>
     5 #include <cstdlib>
     6 #include <cstdio>
     7 #include <vector>
     8 #include <cmath>
     9 #include <queue>
    10 #include <stack>
    11 #include <map>
    12 #include <set>
    13 #define inf (1<<30)
    14 #define N (200010)
    15 #define il inline
    16 #define RG register
    17 #define ll long long
    18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    19 
    20 using namespace std;
    21 
    22 struct edge{ int u,v; }g[N];
    23 
    24 int ans[N],fa[N],vis[N],st[25*N],q[N][5],n,m,k,tim,top;
    25 
    26 il int gi(){
    27     RG int x=0,q=1; RG char ch=getchar();
    28     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    29     if (ch=='-') q=-1,ch=getchar();
    30     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
    31     return q*x;
    32 }
    33 
    34 il int find(RG int x){
    35     if (fa[x]==x) return x;
    36     st[++top]=x,st[++top]=fa[x];
    37     return fa[x]=find(fa[x]);
    38 }
    39 
    40 il void unionn(RG int u,RG int v){
    41     if (find(u)!=find(v)){
    42     st[++top]=fa[u];
    43     st[++top]=fa[fa[u]];
    44     fa[fa[u]]=fa[v];
    45     }
    46     return;
    47 }
    48 
    49 il void solve(RG int l,RG int r){
    50     RG int mid=(l+r)>>1,now=top,flag=1; ++tim;
    51     if (l==r){
    52     for (RG int i=1;i<=q[l][0] && flag;++i)
    53         if (find(g[q[l][i]].u)!=find(g[q[l][i]].v)) flag=0;
    54     for (;top>now;top-=2) fa[st[top-1]]=st[top]; ans[l]=flag; return;
    55     }
    56     for (RG int i=l;i<=mid;++i)
    57     for (RG int j=1;j<=q[i][0];++j) vis[q[i][j]]=tim;
    58     for (RG int i=mid+1;i<=r;++i)
    59     for (RG int j=1;j<=q[i][0];++j)
    60         if (vis[q[i][j]]!=tim) unionn(g[q[i][j]].u,g[q[i][j]].v);
    61     solve(l,mid),++tim; for (;top>now;top-=2) fa[st[top-1]]=st[top];
    62     for (RG int i=mid+1;i<=r;++i)
    63     for (RG int j=1;j<=q[i][0];++j) vis[q[i][j]]=tim;
    64     for (RG int i=l;i<=mid;++i)
    65     for (RG int j=1;j<=q[i][0];++j)
    66         if (vis[q[i][j]]!=tim) unionn(g[q[i][j]].u,g[q[i][j]].v);
    67     solve(mid+1,r); for (;top>now;top-=2) fa[st[top-1]]=st[top]; return;
    68 }
    69 
    70 il void work(){
    71     n=gi(),m=gi(),tim=1; for (RG int i=1;i<=n;++i) fa[i]=i;
    72     for (RG int i=1;i<=m;++i) g[i].u=gi(),g[i].v=gi(); k=gi();
    73     for (RG int i=1;i<=k;++i){
    74     q[i][0]=gi();
    75     for (RG int j=1;j<=q[i][0];++j) q[i][j]=gi(),vis[q[i][j]]=tim;
    76     }
    77     for (RG int i=1;i<=m;++i) if (!vis[i]) unionn(g[i].u,g[i].v); solve(1,k);
    78     for (RG int i=1;i<=k;++i) puts(ans[i] ? "Connected" : "Disconnected"); return;
    79 }
    80 
    81 int main(){
    82     File("graph");
    83     work();
    84     return 0;
    85 }
  • 相关阅读:
    数据结构相关概念
    树的创建与遍历
    Java探索之旅(18)——多线程(2)
    Java探索之旅(17)——多线程(1)
    Java Servlet 笔记4
    Java Servlet 笔记3
    Java Servlet 笔记2
    Java Servlet 笔记1
    JavaBean实现用户登陆
    基于SSE4和多核编程的电子相册的实现
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6970364.html
Copyright © 2011-2022 走看看