【BZOJ3237】【AHOI2013】连通图 [CDQ分治]
连通图
Time Limit: 20 Sec Memory Limit: 512 MB
[Submit][Status][Discuss]
Description

Input

Output

Sample Input
1 2
2 3
3 4
4 1
2 4
3
1 5
2 2 3
2 1 2
Sample Output
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分治]的更多相关文章
- 2018.10.01 bzoj3237: [Ahoi2013]连通图(cdq分治+并查集)
传送门 cdq分治好题. 对于一条边,如果加上它刚好连通的话,那么删掉它会有两个大集合A,B.于是我们先将B中禁用的边连上,把A中禁用的边禁用,再递归处理A:然后把A中禁用的边连上,把B中禁用的边禁用 ...
- [BZOJ3237][AHOI2013]连通图(分治并查集)
3237: [Ahoi2013]连通图 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1736 Solved: 655[Submit][Status ...
- BZOJ 3237([Ahoi2013]连通图-cdq图重构-连通性缩点)
3237: [Ahoi2013]连通图 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 106 Solved: 31 [ Submit][ St ...
- BZOJ3237: [Ahoi2013]连通图
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3237 cdq分治+缩点. 可以每次处理的时候把除l~r之外的边的端点都连起来.然后去跑cdq分 ...
- 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 ...
- BZOJ3237 AHOI2013连通图(线段树分治+并查集)
把查询看做是在一条时间轴上.那么每条边都有几段存在时间.于是线段树分治就好了. 然而在bzoj上t掉了,不知道是常数大了还是写挂了. 以及brk不知道是啥做数组名过不了编译. #include< ...
- bzoj3569 DZY Loves Chinese II & bzoj3237 [AHOI2013] 连通图
给一个无向连通图,多次询问,每次询问给 k 条边,问删除这 k 条边后图的连通性,对于 bzoj3237 可以离线,对于 bzoj3569 强制在线 $n,m,q \leq 500000,k \leq ...
- 【BZOJ3456】轩辕朗的城市规划 无向连通图计数 CDQ分治 FFT 多项式求逆 多项式ln
题解 分治FFT 设\(f_i\)为\(i\)个点组成的无向图个数,\(g_i\)为\(i\)个点组成的无向连通图个数 经过简单的推导(枚举\(1\)所在的连通块大小),有: \[ f_i=2^{\f ...
- 【线段树分治】【P5227】 [AHOI2013]连通图
Description 给定一个无向连通图和若干个小集合,每个小集合包含一些边,对于每个集合,你需要确定将集合中的边删掉后改图是否保持联通.集合间的询问相互独立 定义一个图为联通的当且仅当对于任意的两 ...
随机推荐
- echarts的pie图中,各区块颜色的调整
今天在学习使用echarts生成各种图表. 然后在使用pie图时出现我无论怎么更改代码中的颜色,pie图中各块的颜色都十分相近,几乎没法区别块与块之间的区别,如下图: 在下图中,除了其中一块的是红色的 ...
- https 通信流程和Charles 抓包原理
1. https 通信流程 ①客户端的浏览器向服务器传送客户端SSL 协议的版本号,加密算法的种类,产生的随机数,以及其他服务器和客户端之间通讯所需要的各种信息.②服务器向客户端传送SSL 协议的版本 ...
- Linux开发C语言规范
-Iinclude:找头文件目录 ,获取头文件的目录 -C:创建.o文件 .h:文件用来声明函数,即写一个函数名. 如 int add(); int div(); int mul(); .c:文件定义 ...
- linux备忘录-shell脚本
知识 shell执行方式 shell执行方式有 通过source或. 在现在的bash环境中执行脚本 变量等会保持 通过bash shell.sh或sh shell.sh 使用一个新的bash环境执行 ...
- 并查集——poj1703(带权并查集入门)
传送门:Find them, Catch them 题意:警察抓获N个罪犯,这些罪犯只可能属于两个团伙中的一个,现在给出M个条件(D a b表示a和b不在同一团伙),对于每一个询问(A a b)确定a ...
- 软件工程项目组Z.XML会议记录 2013/11/27
软件工程项目组Z.XML会议记录 [例会时间]2013年11月27日星期三21:00-22:00 [例会形式]小组讨论 [例会地点]学生公寓3号楼会客厅 [例会主持]罗凡 [会议记录]罗凡 会议整体流 ...
- 剑指offer:正则表达式匹配
目录 题目 解题思路 具体代码 题目 题目链接 剑指offer:正则表达式匹配 题目描述 请实现一个函数用来匹配包括'.'和'*'的正则表达式.模式中的字符.表示任意一个字符,而*表示它前面的字符可以 ...
- CentOS6.8单独编译安装PHP gd库扩展
# PHP-GD安装 #在安装之前可以先更新一下yum源,可以使用国内的阿里云源 yum -y install libjpeg-turbo-devel yum -y install freetype- ...
- new String(str.getBytes(“gbk”),“gbk”)的用法详解
new String(str.getBytes(“gbk”),“gbk”)的用法详解 前提是str存放的是汉字 一.如果是new String(str.getBytes(“gbk”),“gbk”)时, ...
- Intellij IDEA将工程打包成jar包并执行
打开File -> Project Structure -> Artifacts 点击“+”,选择“Jar”,选择Empty或From modules with dependencies, ...