题意

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

  • \(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. Struts2 源码分析-----Hello world

    今天第一天学习struts2,没学过怎么办,那当然是helloworld.感觉嘛,学习的基本流程都差不多,就是helloworld,开发环境,然后就是逐个按照知识点打demo,打着打着你就会发现str ...

  2. Python接入支付宝进行PC端支付

    1.  支付宝开放平台登录,使用支付宝账号登录 https://open.alipay.com/platform/home.htm 2.选择沙箱模式 [支付宝提供了测试环境] https://docs ...

  3. .gitignore梳理

    参考来源: https://www.cnblogs.com/kevingrace/p/5690241.html 对于经常使用Git的朋友来说,.gitignore配置一定不会陌生.废话不说多了,接下来 ...

  4. logback的加载过程

    使用logback-classic.jar时,启动应用后,logback按照以下顺序进行扫描: 1.在系统配置文件System Properties中寻找是否有logback.configuratio ...

  5. silverlight数据绑定模式TwoWay,OneWay,OneTime的研究

    asp.net开发中,数据绑定是一个很简单的概念,控件与数据绑定后,控件可以自动把数据按一定的形式显示出来.(当然控件上的值改变后,可以通过提交页面表单,同时后台服务端代码接收新值更新数据) silv ...

  6. 【extjs6学习笔记】1.10 初始: 定义类

    http://www.extjs-tutorial.com/extjs/define-new-class-in-extjs

  7. 巧用netsh命令实现端口转发(端口映射)不求人

    好处:即时生效,随意修改删除,不影响其他ip映射 记事本保存为bat格式批量添加后,并查看映射: netsh interface portproxy add v4tov4 listenport=701 ...

  8. win8.1和wp8.1共用代码,需要注意的一些问题

    最近写了一个应有,使用了mvvmlight,把viewmodel.model.common之类的代码都放到了shared共享,写下来才发现,有不少问题是自已下手之前没注意到的,有些地方实在没法中途改了 ...

  9. POJ 2718 Smallest Difference(dfs,剪枝)

    枚举两个排列以及有那些数字,用dfs比较灵活. dfs1是枚举长度短小的那个数字,dfs2会枚举到比较大的数字,然后我们希望低位数字的差尽量大, 后面最优全是0,如果全是0都没有当前ans小的话就剪掉 ...

  10. spring-boot自定义启动端口

    有时候我们可能需要启动不止一个SpringBoot,而SpringBoot默认的端口号是8080,所以这时候我们就需要修改SpringBoot的默认端口了.修改SpringBoot的默认端口有两种方式 ...