HDU 3896 Greatest TC 双连通分量
题意
给一个连通的无向图,有两种询问:
- \(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 双连通分量的更多相关文章
- 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 ...
- HDU 4005 The war 双连通分量 缩点
题意: 有一个边带权的无向图,敌人可以任意在图中加一条边,然后你可以选择删除任意一条边使得图不连通,费用为被删除的边的权值. 求敌人在最优的情况下,使图不连通的最小费用. 分析: 首先求出边双连通分量 ...
- HDU 2460 Network 边双连通分量 缩点
题意: 给出一个无向连通图,有\(m\)次操作,每次在\(u, v\)之间加一条边,并输出此时图中桥的个数. 分析: 先找出边双连通分量然后缩点得到一棵树,树上的每条边都输原图中的桥,因此此时桥的个数 ...
- HDU3896 Greatest TC(双联通分量+倍增)
Problem Description TC (Tian Chao) is magical place, as you all know...The railways and the rail-sta ...
- HDU 2242 考研路茫茫——空调教室(边双连通分量+树形dp+重边标号)
http://acm.hdu.edu.cn/showproblem.php?pid=2242 题意: 思路:首先求一下双连通分量,如果只有一个双连通分量,那么无论断哪根管子,图还是连通的. 最后只需要 ...
- hdu 2460(tarjan求边双连通分量+LCA)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2460 思路:题目的意思是要求在原图中加边后桥的数量,首先我们可以通过Tarjan求边双连通分量,对于边 ...
- HDU 4612——Warm up——————【边双连通分量、树的直径】
Warm up Time Limit:5000MS Memory Limit:65535KB 64bit IO Format:%I64d & %I64u Submit Stat ...
- 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 ...
- 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 ...
随机推荐
- Struts2 源码分析-----Hello world
今天第一天学习struts2,没学过怎么办,那当然是helloworld.感觉嘛,学习的基本流程都差不多,就是helloworld,开发环境,然后就是逐个按照知识点打demo,打着打着你就会发现str ...
- Python接入支付宝进行PC端支付
1. 支付宝开放平台登录,使用支付宝账号登录 https://open.alipay.com/platform/home.htm 2.选择沙箱模式 [支付宝提供了测试环境] https://docs ...
- .gitignore梳理
参考来源: https://www.cnblogs.com/kevingrace/p/5690241.html 对于经常使用Git的朋友来说,.gitignore配置一定不会陌生.废话不说多了,接下来 ...
- logback的加载过程
使用logback-classic.jar时,启动应用后,logback按照以下顺序进行扫描: 1.在系统配置文件System Properties中寻找是否有logback.configuratio ...
- silverlight数据绑定模式TwoWay,OneWay,OneTime的研究
asp.net开发中,数据绑定是一个很简单的概念,控件与数据绑定后,控件可以自动把数据按一定的形式显示出来.(当然控件上的值改变后,可以通过提交页面表单,同时后台服务端代码接收新值更新数据) silv ...
- 【extjs6学习笔记】1.10 初始: 定义类
http://www.extjs-tutorial.com/extjs/define-new-class-in-extjs
- 巧用netsh命令实现端口转发(端口映射)不求人
好处:即时生效,随意修改删除,不影响其他ip映射 记事本保存为bat格式批量添加后,并查看映射: netsh interface portproxy add v4tov4 listenport=701 ...
- win8.1和wp8.1共用代码,需要注意的一些问题
最近写了一个应有,使用了mvvmlight,把viewmodel.model.common之类的代码都放到了shared共享,写下来才发现,有不少问题是自已下手之前没注意到的,有些地方实在没法中途改了 ...
- POJ 2718 Smallest Difference(dfs,剪枝)
枚举两个排列以及有那些数字,用dfs比较灵活. dfs1是枚举长度短小的那个数字,dfs2会枚举到比较大的数字,然后我们希望低位数字的差尽量大, 后面最优全是0,如果全是0都没有当前ans小的话就剪掉 ...
- spring-boot自定义启动端口
有时候我们可能需要启动不止一个SpringBoot,而SpringBoot默认的端口号是8080,所以这时候我们就需要修改SpringBoot的默认端口了.修改SpringBoot的默认端口有两种方式 ...