连通图

Time Limit: 20 Sec  Memory Limit: 512 MB
[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

Main idea

  给定一张无向联通图,询问删除掉若干条边后图是否联通,多次询问。

Solution

  首先我们看到删边判联通,第一反应想到了LCT,由于图不是一棵树,无法用LCT实现,那么我们否决掉了动态维护的方法。
  根据可以离线询问这一特征来思考如何操作,发现k(询问数)<=100000,显然是log级别的做法,结合可离线的特征,这时候只剩下了对于所有询问一起进行操作的方法 ,现在我们得出了算法:CDQ分治。
  发现直接删边操作较为困难,我们逆向思维,考虑如何在一个空的图上加边
  先考虑只有两个询问的情况,假定我们的询问删边集合为A,B,那么显然想到了先把不在A中并且不在B中边加入(这时称其为状态一),然后分开处理,先加入不在A中但是在B中的边,判下是否联通就得到了A中的答案,然后回到状态一,加入不在B中在A中的边,判断一下得到了B的答案
  然后基于这样的整个思路,我们考虑如何将两个集合拓展到多个集合
  立马想到了分治,对于所有集合分治使其类同于A,B两种“大集合”,然后继续分治,最后必然可以归于仅有两个小集合的情况,然后向上回溯即可。加边用并查集加入即可。
  我们来整理一下CDQ分治的思路:
    1、加入不在左区间但在右区间的边;
    2、对于左区间继续分治;
    3、回到上一层的状态(在分治的时候记录并查集中改变了的父子关系,暴力修改回去即可)
    4、加入不在右区间但在左区间的边;
    5、对于右区间继续分治;
    ……
  最后判断是否联通的时候又发现一开始的整张图是处于连通状态的,所以我们只要判断删掉的边的端点是否连通即可。

Code

 #include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<queue>
using namespace std; const int ONE=; int n,m,Bian;
int fat[ONE],cnt;
int PD[ONE];
int Ans[ONE]; struct power
{
int x,y;
}a[ONE*],q[ONE*]; struct point
{
int c;
int b[];
}quey[ONE]; int get()
{
int res,Q=; char c;
while( (c=getchar())< || c>)
if(c=='-')Q=-;
if(Q) res=c-;
while((c=getchar())>= && c<=)
res=res*+c-;
return res*Q;
} int Find(int x)
{
if(x!=fat[x])
{
q[++cnt].x=x; q[cnt].y=fat[x];
fat[x]=Find(fat[x]);
}
return fat[x];
} void Un(int x,int y)
{
int f1=Find(x);
int f2=Find(y);
if(f1!=f2)
{
q[++cnt].x=f2; q[cnt].y=fat[f2];
fat[f2]=f1;
}
} int Get_pd(int l)
{
int pd=;
for(int i=;i<=quey[l].c;i++)
{
int j=quey[l].b[i];
if(Find(a[j].x) != Find(a[j].y))
{
pd=;
break;
}
}
return pd;
} void Mark(int l,int r,int t)
{
for(int i=l;i<=r;i++)
{
for(int j=;j<=quey[i].c;j++)
PD[quey[i].b[j]]=t;
}
} void Add(int l,int r)
{
for(int i=l;i<=r;i++)
{
for(int j=;j<=quey[i].c;j++)
{
int num=quey[i].b[j];
if(PD[num]) continue;
Un(a[num].x,a[num].y);
}
}
} void Back(int Now_cnt)
{
for(;cnt>Now_cnt;cnt--)
fat[q[cnt].x]=q[cnt].y;
} void CDQ(int l,int r)
{
if(l==r)
{
Ans[l]=Get_pd(l);
return;
} int Now_cnt=cnt;
int mid=(l+r)/;
Mark(l,mid,); Add(mid+,r); Mark(l,mid,);
CDQ(l,mid); Back(Now_cnt);
Mark(mid+,r,); Add(l,mid); Mark(mid+,r,);
CDQ(mid+,r);
} int main()
{
n=get(); Bian=get();
for(int i=;i<=n;i++) fat[i]=i;
for(int i=;i<=Bian;i++)
{
a[i].x=get(); a[i].y=get();
} m=get();
for(int i=;i<=m;i++)
{
quey[i].c=get();
for(int j=;j<=quey[i].c;j++)
quey[i].b[j]=get();
} Mark(,m,);
for(int i=;i<=Bian;i++)
{
if(PD[i]) continue;
Un(a[i].x,a[i].y);
}
Mark(,m,); cnt=; CDQ(,m); for(int i=;i<=m;i++)
{
if(Ans[i]) printf("Connected");
else printf("Disconnected");
printf("\n");
}
}

【BZOJ3237】【AHOI2013】连通图 [CDQ分治]的更多相关文章

  1. 2018.10.01 bzoj3237: [Ahoi2013]连通图(cdq分治+并查集)

    传送门 cdq分治好题. 对于一条边,如果加上它刚好连通的话,那么删掉它会有两个大集合A,B.于是我们先将B中禁用的边连上,把A中禁用的边禁用,再递归处理A:然后把A中禁用的边连上,把B中禁用的边禁用 ...

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

    3237: [Ahoi2013]连通图 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1736  Solved: 655[Submit][Status ...

  3. BZOJ 3237([Ahoi2013]连通图-cdq图重构-连通性缩点)

    3237: [Ahoi2013]连通图 Time Limit: 20 Sec   Memory Limit: 512 MB Submit: 106   Solved: 31 [ Submit][ St ...

  4. BZOJ3237: [Ahoi2013]连通图

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3237 cdq分治+缩点. 可以每次处理的时候把除l~r之外的边的端点都连起来.然后去跑cdq分 ...

  5. 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 Connec ...

  6. BZOJ3237 AHOI2013连通图(线段树分治+并查集)

    把查询看做是在一条时间轴上.那么每条边都有几段存在时间.于是线段树分治就好了. 然而在bzoj上t掉了,不知道是常数大了还是写挂了. 以及brk不知道是啥做数组名过不了编译. #include< ...

  7. bzoj3569 DZY Loves Chinese II & bzoj3237 [AHOI2013] 连通图

    给一个无向连通图,多次询问,每次询问给 k 条边,问删除这 k 条边后图的连通性,对于 bzoj3237 可以离线,对于 bzoj3569 强制在线 $n,m,q \leq 500000,k \leq ...

  8. 【BZOJ3456】轩辕朗的城市规划 无向连通图计数 CDQ分治 FFT 多项式求逆 多项式ln

    题解 分治FFT 设\(f_i\)为\(i\)个点组成的无向图个数,\(g_i\)为\(i\)个点组成的无向连通图个数 经过简单的推导(枚举\(1\)所在的连通块大小),有: \[ f_i=2^{\f ...

  9. 【线段树分治】【P5227】 [AHOI2013]连通图

    Description 给定一个无向连通图和若干个小集合,每个小集合包含一些边,对于每个集合,你需要确定将集合中的边删掉后改图是否保持联通.集合间的询问相互独立 定义一个图为联通的当且仅当对于任意的两 ...

随机推荐

  1. java doc 编写

    总而言之,我觉得有用的是: @see 只要敲了@see 然后会自动写你的类名的,很方便.# 去连接字段 {@link } 只要敲了{@link } 然后会自动写你的类名的,很方便.# 去连接字段 如果 ...

  2. Office Web Apps Server(1)

         Office Web Apps Server runs on one or more servers and provides browser-based Office file viewi ...

  3. list 集合addAll 和 add 方法小坑

    1.问题 我们经常会遍历 list集合,在遍历的过程中,如果在遍历的过程中添加了 add()  或者 addAll() 方法修改了遍历的list列表,那么会报错. 代码演示: List<Inte ...

  4. 第十二篇 Python函数之全局变量&局部变量&递归函数

    全局变量:在定义的时候,顶头写的,没有任何缩进的变量就是全局变量. 全局变量的特点:在当前文件里的任何地方都可以进行调用 局部变量:在子程序里定义的变量,就是局部变量. 子程序:比如.py文件里,写的 ...

  5. 玩玩自动化测试之selenium篇

    现如今社会科技发展太快了,纯功能点点点已经落后别人好几条街了,所以为了让自己多点职业生涯年限,得挺起肩,傲起头.自动化测试,其本质是用代码程序测试程序,所以其实第一步应该学好编程语言,后再自己开发自动 ...

  6. 【java并发编程实战】第六章:线程池

    1.线程池 众所周知创建大量线程时代价是非常大的: - 线程的生命周期开销非常大:创建需要时间,导致延迟处理请求,jvm需要分配空间. - 资源消耗:线程需要占用空间,如果线程数大于可用的处理器数量, ...

  7. 九度OJ--Q1165

    import java.util.ArrayList;import java.util.Scanner; /* * 题目描述: * 读入数据string[ ],然后读入一个短字符串.要求查找strin ...

  8. POJ 2162 Document Indexing(模拟)

    Description Andy is fond of old computers. He loves everything about them and he uses emulators of o ...

  9. java正则表达式 3 -- 查找

    用正则表达式执行查找命令,则需要用正则对象,其规则和执行顺序如下: 指定为字符串的正则表达式必须首先被便以为此类的实例.然后,可将得到的正则对象匹配任意的字符串用于创建Mather对象,执行匹配所涉及 ...

  10. iOS-调用百度地图,苹果自带地图,高德地图,谷歌地图导航方法

    - (void)actionSheet : (ServiceNetworkModel *)model{ __block NSString *urlScheme = @"demoURI://& ...