题意

给一个连通的无向图,有两种询问:

  • \(a, b, c, d\),问如果删掉\(c,d\)之间的边,\(a,b\)之间是否还连通
  • \(a, b, c\),问如果删掉顶点\(c\),\(a,b\)之间是否还连通

分析

首先DFS一遍求出进入节点的时间戳\(pre(u)\),离开节点的时间戳\(post(u)\)以及当前节点的子树中能连接到的最小的DFS序\(low(u)\)。

然后预处理一下\(u\)的\(2^i\)级祖先,方便计算\(u\)的任意级祖先。

考虑第一种查询

不妨设\(c\)是\(d\)的儿子节点,如果\(c,d\)之间是一个桥并且\(a,b\)两个节点一个在\(c\)的子树中一个不在,这种情况下是不连通的。

其他情况都是连通的。

考虑第二种查询

分成三种情况讨论:

  • \(a,b\)都在子树\(c\)中,如果\(a,b\)在\(c\)的同一个儿子子树中那么去掉\(c\)是连通的。

    否则,让\(a,b\)往上跳,变成\(c\)的两个儿子。如果\(low(a) \geq pre(c)\)或\(low(b) \geq pre(c)\)有一个成立,那么是不连通的。

  • \(a,b\)只有一个在子树\(c\)中,由于对称性,不妨假设\(a\)在子树\(c\)中。

    同样让\(a\)往上跳,变成\(c\)的儿子。如果\(low(a) \geq pre(c)\)那么不连通,否则连通。

  • \(a,b\)都不在子树\(c\)中,那么去掉\(c\)完全没有任何影响,所以还是连通的。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = 100000 + 10;
const int maxm = 1000000 + 10; struct Edge
{
int v, nxt;
Edge() {}
Edge(int v, int nxt): v(v), nxt(nxt) {}
}; int ecnt, head[maxn];
Edge edges[maxm]; void AddEdge(int u, int v) {
edges[ecnt] = Edge(v, head[u]); head[u] = ecnt++;
edges[ecnt] = Edge(u, head[v]); head[v] = ecnt++;
} int n, m; int fa[maxn], dep[maxn];
int dfs_clock, pre[maxn], post[maxn], low[maxn];
bool isbridge[maxn], iscut[maxn]; void dfs(int u) {
bool flag = false;
int child = 0;
pre[u] = low[u] = ++dfs_clock;
for(int i = head[u]; ~i; i = edges[i].nxt) {
int v = edges[i].v;
if(v == fa[u] && !flag) { flag = true; continue; }
child++;
if(!pre[v]) {
fa[v] = u;
dep[v] = dep[u] + 1;
dfs(v);
low[u] = min(low[u], low[v]);
if(low[v] >= pre[u]) {
iscut[u] = true;
if(low[v] > pre[u]) isbridge[v] = true;
}
} else low[u] = min(low[u], pre[v]);
}
if(u == 1 && child == 1) iscut[u] = false;
post[u] = dfs_clock;
} int anc[maxn][20]; void preprocess() {
memset(anc, 0, sizeof(anc));
for(int i = 1; i <= n; i++) anc[i][0] = fa[i];
for(int j = 1; (1 << j) < n; j++)
for(int i = 1; i <= n; i++) if(anc[i][j-1])
anc[i][j] = anc[anc[i][j-1]][j-1];
} int upward(int u, int x) {
for(int i = 0; i < 20; i++)
if((x >> i) & 1) u = anc[u][i];
return u;
} int insubtree(int u, int v) {
if(pre[v] <= pre[u] && pre[u] <= post[v]) return 1;
return 0;
} bool juedgeVertex(int a, int b, int c) {
int in1 = insubtree(a, c);
int in2 = insubtree(b, c);
if(in1 & in2) {
a = upward(a, dep[a] - dep[c] - 1);
b = upward(b, dep[b] - dep[c] - 1);
if(a == b) return true;
if(low[a] >= pre[c]) return false;
if(low[b] >= pre[c]) return false;
}
if(in1 ^ in2) {
if(!in1) swap(a, b);
a = upward(a, dep[a] - dep[c] - 1);
if(low[a] >= pre[c]) return false;
}
return true;
} int main()
{
while(scanf("%d%d", &n, &m) == 2) {
ecnt = 0;
memset(head, -1, sizeof(head));
while(m--) {
int u, v;
scanf("%d%d", &u, &v);
AddEdge(u, v);
} dfs_clock = 0;
memset(pre, 0, sizeof(pre));
memset(isbridge, false, sizeof(isbridge));
memset(iscut, false, sizeof(iscut));
dfs(1);
preprocess(); int q;
scanf("%d", &q);
while(q--) {
int op, a, b, c, d;
scanf("%d%d%d%d", &op, &a, &b, &c);
bool ok = true;
if(op == 1) {
scanf("%d", &d);
if(dep[c] < dep[d]) swap(c, d);
int in1 = insubtree(a, c);
int in2 = insubtree(b, c);
if(isbridge[c] && (in1 ^ in2) == 1) ok = false;
} else {
ok = juedgeVertex(a, b, c);
}
printf("%s\n", ok ? "yes" : "no");
}
} return 0;
}

HDU 3896 Greatest TC 双连通分量的更多相关文章

  1. HDU 5458 Stability(双连通分量+LCA+并查集+树状数组)(2015 ACM/ICPC Asia Regional Shenyang Online)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5458 Problem Description Given an undirected connecte ...

  2. HDU 4005 The war 双连通分量 缩点

    题意: 有一个边带权的无向图,敌人可以任意在图中加一条边,然后你可以选择删除任意一条边使得图不连通,费用为被删除的边的权值. 求敌人在最优的情况下,使图不连通的最小费用. 分析: 首先求出边双连通分量 ...

  3. HDU 2460 Network 边双连通分量 缩点

    题意: 给出一个无向连通图,有\(m\)次操作,每次在\(u, v\)之间加一条边,并输出此时图中桥的个数. 分析: 先找出边双连通分量然后缩点得到一棵树,树上的每条边都输原图中的桥,因此此时桥的个数 ...

  4. HDU3896 Greatest TC(双联通分量+倍增)

    Problem Description TC (Tian Chao) is magical place, as you all know...The railways and the rail-sta ...

  5. HDU 2242 考研路茫茫——空调教室(边双连通分量+树形dp+重边标号)

    http://acm.hdu.edu.cn/showproblem.php?pid=2242 题意: 思路:首先求一下双连通分量,如果只有一个双连通分量,那么无论断哪根管子,图还是连通的. 最后只需要 ...

  6. hdu 2460(tarjan求边双连通分量+LCA)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2460 思路:题目的意思是要求在原图中加边后桥的数量,首先我们可以通过Tarjan求边双连通分量,对于边 ...

  7. HDU 4612——Warm up——————【边双连通分量、树的直径】

    Warm up Time Limit:5000MS     Memory Limit:65535KB     64bit IO Format:%I64d & %I64u Submit Stat ...

  8. HDU 3686 Traffic Real Time Query System(双连通分量缩点+LCA)(2010 Asia Hangzhou Regional Contest)

    Problem Description City C is really a nightmare of all drivers for its traffic jams. To solve the t ...

  9. HDU 4612 Warm up(2013多校2 1002 双连通分量)

    Warm up Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Su ...

随机推荐

  1. 一、 Spring Cloud Eureka ,咱们先跑起来

    一.Spring Cloud 简介 Spring Cloud 是一个基于Spring Boot 实现的微服务架构开发工具.是一个涉及到服务治理.分布式配置管理.负载均衡.服务容错.API网关.消息总线 ...

  2. 洛谷 P1281 书的复制

    书的复制 Code: #include <iostream> #include <cstdio> #include <cstring> using namespac ...

  3. Retrofit 2.0 轻松实现多文件/图片上传/Json字符串/表单

    如果嫌麻烦直接可以用我封装好的库:Novate: https://github.com/Tamicer/Novate 通过对Retrofit2.0的前两篇的基础入门和案例实践,掌握了怎么样使用Retr ...

  4. Eucalyptus常用查询命令

    前言: Elastic Utility Computing Architecture for Linking Your Programs To Useful Systems (Eucalyptus)  ...

  5. Error: unknown argument: '-websockets'

    参考原文:http://www.cocoachina.com/bbs/read.php?tid=194014 解决方法:点击项目右边编辑区域上面有一个building setting找到other l ...

  6. 报错:无法打开"cocos-ext.h" /添加第三方库

    参考原文:http://lin-jianlong.diandian.com/post/2012-11-05/40042951271 1.项目属性->配置属性->C/C++->常规-& ...

  7. 洛谷 P1951 收费站_NOI导刊2009提高(2)

    题目描述 在某个遥远的国家里,有n个城市.编号为1,2,3,…,n. 这个国家的政府修建了m条双向的公路.每条公路连接着两个城市.沿着某条公路,开车从一个城市到另一个城市,需要花费一定的汽油. 开车每 ...

  8. [转载]AngularJS入门教程01:静态模板

    为了说明angularJS如何增强了标准HTML,我们先将创建一个静态HTML页面模板,然后把这个静态HTML页面模板转换成能动态显示的AngularJS模板. 在本步骤中,我们往HTML页面中添加两 ...

  9. Opentsdb简介

    1.OpenTSDB介绍 1.1.OpenTSDB是什么?主要用途是什么? 官方文档这样描述:OpenTSDB is a distributed, scalable Time Series Datab ...

  10. Java环境变量搭建(Linux环境)

    1. 下载解压JDK压缩包 例如:解压到 /opt/jdk1.7.0_80 下 2. 添加环境变量到 /etc/profile 文件中 vi /etc/profile 在文件末尾追加如下内容: exp ...