题意

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

  • \(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. 使用SpringSession管理分布式系统的会话Session

    在我方供应链项目分布式部署的环境下,需要在统一网关服务中管理访问的Session,即无论访问请求路由到哪一个网关服务环境,使用的都是相同的HttpSession,这样就保证了在用户登录之后,能够使用统 ...

  2. 添加egit插件

    1.下载egit插件 打开Eclipse,git需要eclipse授权,通过网页是无法下载egit的安装包的.在菜单栏依次打开eclipse→help→install new software→add ...

  3. linux 下源码编译环境配置

    yum install -y apr* autoconf automake bison bzip2 bzip2* compat* cpp curl curl-devel \ fontconfig fo ...

  4. char*、string、CString各种字符串之间转换

    参考博客: http://blog.csdn.net/luoweifu/article/details/20242307 http://blog.csdn.net/luoweifu/article/d ...

  5. cesium加载shp格式数据

    方法一: shp格式转换为GeoJson格式并加载 首先注意shp的坐标系,要转换为WGS84,使用arcgis或QGIS 工具:http://mapshaper.org/: 注意:export时,输 ...

  6. Android多媒体框架总结(1) - 利用MediaMuxer合成音视频数据流程分析

    场景介绍: 设备端通过服务器传向客户端(Android手机)实时发送视频数据(H.264)和音频数据(g711a或g711u), 需要在客户端将音视频数据保存为MP4文件存放在本地,用户可以通过APP ...

  7. js 对象字面量

    对象字面量的输出方式以及定义好处 1.对象字面量的输出方式有两种:传统的'.' 例如:box.name 以及数组方式,只不过用数组方式输出时,方括号里面要用引号括起来 例如:box['name'] v ...

  8. IOS UIImageView的帧动画

    ● UIImageView可以让一系列的图片在特定的时间内按顺序显示 ● 相关属性解析: ● animationImages:要显示的图片(一个装着UIImage的NSArray) ● animati ...

  9. innobackupex备份脚本

    #!/bin/bash # 10 23 * * * /bin/bash /data/script/backup.sh BDATE=`date +%Y%m%d%H%M%S`BPATH=/data/bac ...

  10. 牛客NOIP提高组R1 C保护(主席树)

    题意 题目链接 Sol Orz lyq 我们可以把一支军队(u, v)拆分为两个(u, lca)和(v, lca) 考虑一个点x,什么时候军队对它有贡献,肯定是u或v在他的子树内,且lca在他的子树外 ...