【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 给定一个无向连通图和若干个小集合,每个小集合包含一些边,对于每个集合,你需要确定将集合中的边删掉后改图是否保持联通.集合间的询问相互独立 定义一个图为联通的当且仅当对于任意的两 ...
随机推荐
- Ubuntu中搭建Hadoop集群(简记)
stp1:在Vmware虚拟机上创建Ubantu.2环境 步骤:文件—>新建虚拟机—>典型(下一步)—>下一步——>位置(不建议放c盘,文件地址一定要全英文)—>下一步— ...
- 利尔达NB-IOT的PSM和eDRX低功耗模式笔记
1. NB-IOT的技术优势,广覆盖,NB-IOT与GPRS和LTE相比较,最大链路预算提升了20dB,相当于提升了100倍,即使在地车车库.地下室.地下管道等普通无线网络信号难以到达的地方也容易覆盖 ...
- Java检测端口的占用情况
突然间想到这个问题,在网上搜了一下 http://blog.csdn.net/danieluk/article/details/18518175 网上有很多文章都是用上面那个方法来解决这个问题的,总感 ...
- ES6 export,import报错
问题描述: 现有两个文件: profile.js const firstName = 'Michael'; const lastName = 'Jackson'; const year = 2018; ...
- Ubuntu-C++环境设置
在学习C++,顺便想熟悉一下Linux下开发 所以就开始搭建Linux环境 第一步就是下载虚拟机和Ubuntu 虚拟机 vm 12.1 Ubuntu 16 VM安装省略 Ubuntu安装省略 下面是我 ...
- XPATH之normalize-space(.)和normalize-space(text())区别
normalize,字面意思就是正规化,加上space大概意思就是空格的处理了. 官方解释是这样的: 通过去掉前导和尾随空白并使用单个空格替换一系列空白字符,使空白标准化.如果省略了该参数,上下文节点 ...
- 用tensorflow实现自然语言处理——基于循环神经网络的神经语言模型
自然语言处理和图像处理不同,作为人类抽象出来的高级表达形式,它和图像.声音不同,图像和声音十分直觉,比如图像的像素的颜色表达可以直接量化成数字输入到神经网络中,当然如果是经过压缩的格式jpeg等必须还 ...
- Mininet实验 动态改变转发规则
介绍 拓扑如下: 在该环境下,假设H1 ping H4,初始的路由规则是S1-S2-S5,一秒后,路由转发规则变为S1-S3-S5,再过一秒,规则变为S1-S4-S5,然后再回到最初的转发规则S1-S ...
- windows redis+lua的调试
1.编写lua脚本my.lua local key = KEYS[1] --限流KEY(一秒一个) local limit = tonumber(ARGV[1]) --限流大小 local curre ...
- 弹框中的elment-form在弹框重新打开后,怎么初始化验证信息
如果弹框关闭前有错误提示,弹框重新打开,由于没重新刷新页面,该错误还是存在.... 解决办法:弹框中的内容写成一个组件,prop接收父元素弹框的状态,并监听且reset表格 1. cnpm insta ...