BZOJ 3237: [Ahoi2013]连通图
3237: [Ahoi2013]连通图
Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 1161 Solved: 399
[Submit][Status][Discuss]
Description
.jpg)
Input
.jpg)
Output
.jpg)
Sample Input
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
很有意思的一道题。乍一看就是LCT,后来听说可以CDQ水过,一想确实哎,写写就1A了。
对于一张图的连通性,我们可以用并查集维护,简单方便,可是不支持删边操作(这里指的是随机的删边)。但发现可以通过记录father数组的更改,得到一个回溯栈,方便地进行顺序删边。
利用CDQ分治的想法,在一个solve(l,r)时,考虑把(mid,r]内的边补回到图中,维护并查集并记录改变(用来回溯),然后递归solve(l,mid),最后回溯;再把[l,mid]的边补回,递归右侧,回溯。这样到底层solve(l,r),即l==r时,并查集维护的刚好不包含当前这组询问中的边,此时记录下答案即可。
#include <bits/stdc++.h>
inline int getC(void) {
static const int siz = ;
static char buf[siz];
static char *hd = buf + siz;
static char *tl = buf + siz;
if (hd == tl)
fread(hd = buf, , siz, stdin);
return int(*hd++);
}
inline int getI(void) {
register int ret = ;
register int neg = false;
register int bit = getC();
for (; bit < ; bit = getC())
if (bit == '-')neg ^= true;
for (; bit > ; bit = getC())
ret = ret * + bit - '';
return neg ? -ret : ret;
}
const int maxn = ;
int n, m, p;
struct edge {
int x, y;
}e[maxn];
struct query {
int k, s[];
bool connect;
}q[maxn];
int fa[maxn];
int sz[maxn];
int cnt[maxn];
inline int find(int u) {
while (fa[u] != u)
u = fa[u];
return u;
}
int stk[maxn], tot;
void solve(int l, int r) {
if (l == r) {
q[l].connect = sz[find()] == n;
return;
}
int mid = (l + r) >> , top = tot;
for (int i = l; i <= mid; ++i)
for (int j = ; j <= q[i].k; ++j)
if (--cnt[q[i].s[j]] == ) {
int x = find(e[q[i].s[j]].x);
int y = find(e[q[i].s[j]].y);
if (x != y) {
if (sz[x] < sz[y])
fa[x] = y, sz[y] += sz[x], stk[++tot] = x;
else
fa[y] = x, sz[x] += sz[y], stk[++tot] = y;
}
}
solve(mid + , r);
while (tot > top) {
int t = stk[tot--];
sz[fa[t]] -= sz[t];
fa[t] = t;
}
for (int i = l; i <= mid; ++i)
for (int j = ; j <= q[i].k; ++j)
++cnt[q[i].s[j]];
for (int i = mid + ; i <= r; ++i)
for (int j = ; j <= q[i].k; ++j)
if (--cnt[q[i].s[j]] == ) {
int x = find(e[q[i].s[j]].x);
int y = find(e[q[i].s[j]].y);
if (x != y) {
if (sz[x] < sz[y])
fa[x] = y, sz[y] += sz[x], stk[++tot] = x;
else
fa[y] = x, sz[x] += sz[y], stk[++tot] = y;
}
}
solve(l, mid);
while (tot > top) {
int t = stk[tot--];
sz[fa[t]] -= sz[t];
fa[t] = t;
}
for (int i = mid + ; i <= r; ++i)
for (int j = ; j <= q[i].k; ++j)
++cnt[q[i].s[j]];
}
signed main(void) {
n = getI();
m = getI();
for (int i = ; i <= n; ++i)
fa[i] = i, sz[i] = ;
for (int i = ; i <= m; ++i)
e[i].x = getI(),
e[i].y = getI();
p = getI();
for (int i = ; i <= p; ++i) {
q[i].k = getI();
for (int j = ; j <= q[i].k; ++j)
++cnt[q[i].s[j] = getI()];
}
for (int i = ; i <= m; ++i)
if (!cnt[i]) {
int x = find(e[i].x);
int y = find(e[i].y);
if (x != y) {
if (sz[x] < sz[y])
fa[x] = y, sz[y] += sz[x];
else
fa[y] = x, sz[x] += sz[y];
}
}
solve(, p);
for (int i = ; i <= p; ++i)
puts(q[i].connect ? "Connected" : "Disconnected");
}
@Author: YouSiki
BZOJ 3237: [Ahoi2013]连通图的更多相关文章
- BZOJ 3237([Ahoi2013]连通图-cdq图重构-连通性缩点)
3237: [Ahoi2013]连通图 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 106 Solved: 31 [ Submit][ St ...
- 3237: [Ahoi2013]连通图 线段树分治
题解: cf765f cf671e bzoj4184 bzoj4552 线段树分治裸题 还是介绍一下线段树分治 这个东西其实挺简单但也挺有用的 可以把删除+插入操作变成只有插入(倒着就是删除) 像这一 ...
- [BZOJ3237][AHOI2013]连通图(分治并查集)
3237: [Ahoi2013]连通图 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1736 Solved: 655[Submit][Status ...
- BZOJ 3233: [Ahoi2013]找硬币
BZOJ 3233: [Ahoi2013]找硬币 标签(空格分隔): OI-BZOJ OI-DP Time Limit: 10 Sec Memory Limit: 64 MB Description ...
- BZOJ 3235: [Ahoi2013]好方的蛇
BZOJ 3235: [Ahoi2013]好方的蛇 标签(空格分隔): OI-BZOJ OI-DP OI-容斥原理 Time Limit: 10 Sec Memory Limit: 64 MB Des ...
- 线段树分治初步学习&洛谷P5227[AHOI2013]连通图
线段树分治 其实思想说起来是比较简单的,我们把这个题里的所有操作(比如连边删边查询balabala)全部拍到一棵线段树上,然后对着整棵树dfs一下求解答案,顺便把操作做一下,回溯的时候撤销一下即可.虽 ...
- bzoj 3237 连通图 - 并查集 - 线段树
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 Disconne ...
- 【bzoj3237】 Ahoi2013—连通图
http://www.lydsy.com/JudgeOnline/problem.php?id=3237 (题目链接) 题意 给出一个无向图,$Q$组询问,每次询问将原图断掉$C$条边后是否还连通. ...
- BZOJ 3238: [Ahoi2013]差异 [后缀数组 单调栈]
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2326 Solved: 1054[Submit][Status ...
随机推荐
- Unity3D中常用的数据结构总结与分析
来到周末,小匹夫终于有精力和时间来更新下博客了.前段时间小匹夫读过一份代码,对其中各种数据结构灵活的使用赞不绝口,同时也大大激发了小匹夫对各种数据结构进行梳理和总结的欲望.正好最近也拜读了若干大神的文 ...
- StringBuilder的使用
今天用到了StringBuilder来拼接查询语句,发现这个真好用,决定做个小结. 百度一个StringBuilder的定义:String 对象是不可改变的.每次使用 System.String 类中 ...
- 【转】将grub2安装到u盘的方法
将grub2安装到u盘的方法 时间:2015-03-21来源:linux网站 作者:linux人 grub2在各大linux发行版中广泛采用,它非常强大,基本上大多数操作系统都是通过它引导起来的,它的 ...
- Java中日期的转化
4.如何取得年月日.小时分秒? 创建java.util.Calendar实例(Calendar.getInstance()),调用其get()方法传入不同的参数即可获得参数所对应的值,如:calend ...
- canvas学习之API整理笔记(一)
其实canvas本身很简单,就是去学习它的API,多看实例,多自己动手练习,多总结.但是canvas的API实在是有点多,对于初学者来说,可能学到一半就止步不前了.我也有这种感觉,在学习的过程中,编写 ...
- 关getClass().getClassLoader()
InputStream is = getClass().getClassLoader().getResourceAsStream("helloworld.properties&q ...
- 通过Wireshark抓包进行Cookie劫持
首先在目标A机器上运行Wireshark并开启浏览器,开启前关闭其他占用网络的软件,这里我拿51CTO.com做测试. 正常登陆51CTO用户中心,此时使用 http.cookie and http. ...
- 阶段一:AsyncTask的三个属性值和四个步骤
“阶段一”是指我第一次系统地学习Android开发.这主要是对我的学习过程作个记录. 最近学到用AsyncTask来处理有关网络的操作.虽然代码看上去不是很复杂,但仍有很多地方有疑惑.所以研读了一下A ...
- Android--Volley框架的使用
一.Volley特点 通信更快,更简单(数据量不大,但网络通信频繁) Get.Post网络请求及网络图像的高效率异步处理 排序(可以通过网络请求的优先级进行处理) 网络请求的缓存 多级别取消请求 和A ...
- UI-切圆角、透明度、取消按钮点击高亮效果、按钮文字带下划线
一.切UIView的某个角为圆角 如果需要将UIView的4个角全部都为圆角,做法相当简单,只需设置其Layer的cornerRadius属性即可(项目需要使用QuartzCore框架).而若要指定某 ...