给你一个图和三个点U,V,W  问你是否存在从U到V和从U到W的两条边不相交路径

先边双缩点 再每个连通分量搞LCA 最后LCA判

#include<bits/stdc++.h>
using namespace std;
#define INF 0xfffffff
#define maxn 200025
#define min(a,b) (a<b?a:b)
int m, n, Time, cnt, top;
int dfn[maxn], block[maxn], low[maxn], Father[maxn], Stack[maxn];
int Bcc[maxn], Bcccnt = ;
vector<int> G[maxn], G2[maxn];
inline void read(int &v) {
v = ;
char c = ;
int p = ;
while (c < '' || c > '') {
if (c == '-') {
p = -;
}
c = getchar();
}
while (c >= '' && c <= '') {
v = (v << ) + (v << ) + c - '';
c = getchar();
}
v *= p;
}
void Tarjan(int u, int fa) {
dfn[u] = low[u] = ++Time;
Father[u] = fa;
Stack[top++] = u;
int len = G[u].size(), v, k = ;
for (int i = ; i < len; i++) {
v = G[u][i];
if (v == fa && !k) {
k ++;
continue;
}
if (!low[v]) {
Tarjan(v, u);
low[u] = min(low[u], low[v]);
} else {
low[u] = min(low[u], dfn[v]);
}
}
if (dfn[u] == low[u]) {
do {
v = Stack[--top];
block[v] = cnt;
} while (u != v);
cnt ++;
}
}
void getBcc(int x, int y) {
Bcc[x] = y;
for (auto v : G[x]) {
if (Bcc[v] == ) {
getBcc(v, y);
}
}
}
int T;
int q, N;
int u, v, c, w; typedef struct {
int from, to, w;
} edge; //这个结构体用来存储边
vector<edge> edges;
//保存边的数组
int grand[maxn][]; //x向上跳2^i次方的节点,x到他上面祖先2^i次方的距离
int depth[maxn];//深度
int root;
bool vis[maxn];
void addedge(int x, int y, int w) { //把边保存起来的函数
edge a = {x, y, w}, b = {y, x, w};
edges.push_back(a);
edges.push_back(b);
G2[x].push_back(edges.size() - );
G2[y].push_back(edges.size() - );
}
void dfs(int x) { //dfs建图
vis[x] = ;
for (int i = ; i <= N; i++) { //第一个几点就全部都是0,第二个节点就有变化了,不理解的话建议复制代码输出下这些数组
grand[x][i] = grand[grand[x][i - ]][i - ]; //倍增 2^i=2^(i-1)+2^(i-1)
}
for (int i = ; i < G2[x].size(); i++) {
edge e = edges[G2[x][i]];
if (e.to != grand[x][]) { //这里我们保存的是双向边所以与他相连的边不是他父亲就是他儿子父亲的话就不能执行,不然就死循环了。
depth[e.to] = depth[x] + ; //他儿子的深度等于他爸爸的加1
grand[e.to][] = x; //与x相连那个节点的父亲等于x
//gwmax[e.to][0]=e.w;
dfs(e.to);//深搜往下面建
}
}
}
int lca(int a, int b) {
if (a == b) {
return a;
}
if (depth[a] > depth[b]) {
swap(a, b); //保证a在b上面,便于计算
}
for (int i = N; i >= ; i--) { //类似于二进制拆分,从大到小尝试
if (depth[a] < depth[b] && depth[grand[b][i]] >= depth[a]) { //a在b下面且b向上跳后不会到a上面
b = grand[b][i]; //先把深度较大的b往上跳
}
}
if (a == b) {
return a;
}
for (int j = N; j >= ; j--) { //在同一高度了,他们一起向上跳,跳他们不相同节点,当全都跳完之后grand【a】【0】就是lca,上面有解释哈。
if (grand[a][j] != grand[b][j]) {
a = grand[a][j];
b = grand[b][j];
}
}
if (grand[a][] == && grand[b][] == && a != b) {
return -;
}
return grand[a][];
} void init(int n) {
edges.clear();
Bcccnt = cnt = ;
top = Time = ;
for (int i = ; i <= n; i++) {
vis[i] = dfn[i] = low[i] = block[i] = Father[i] = Bcc[i] = ;
G[i].clear();
G2[i].clear();
}
}
int main() {
read(T);
while (T--) {
read(n), read(m), read(q);
init(n + );
for (int i = ; i <= m; i++) {
read(u), read(v);
if (u != v) {
G[u].push_back(v);
G[v].push_back(u);
}
}
for (int i = ; i <= n; i++) {
if (Bcc[i] == ) {
getBcc(i, Bcccnt);
Bcccnt++;
}
}
for (int i = ; i <= n; i++) {
if (!low[i]) {
Tarjan(i, i);
}
}
depth[] = -;
N = floor(log(cnt + 0.0) / log(2.0)) + ; //最多能跳的2^i祖先
for (int i = ; i <= n; i++) {
v = Father[i];
if (block[i] != block[v]) {
addedge(block[i], block[v], );
}
}
for (int i = ; i < cnt; i++) {
if (!vis[i]) {
depth[i] = ;
root = i;
dfs(root);
}
}
for (int i = ; i <= q; i++) {
read(u), read(v), read(w);
if (Bcc[u] != Bcc[v] || Bcc[u] != Bcc[w]) {
printf("No\n");
continue;
}
u = block[u], v = block[v], w = block[w];
if (u == v || u == w) {
printf("Yes\n");
continue;
}
if (v == w) {
printf("No\n");
continue;
}
int t[] = {u, lca(u, w), lca(u, v), lca(v, w)};
sort(t, t + , [](int x, int y) {
return depth[x] < depth[y];
});
if (t[] == u && t[] == u) {
printf("Yes\n");
} else {
printf("No\n");
}
}
}
return ;
}

ZOJ 4097 Rescue the Princess 边双缩点+LCA的更多相关文章

  1. ZOJ 4097 Rescue the Princess

    在这个物欲横流的社会 oj冷漠无情 只有这xx还有些温度 越界就越界吧  wrong 怎么回事.... 给出一个图 然后给出q次询问 问是否存在v和w分别到u的路径且边不重复 在边双连通分量中 任意两 ...

  2. POJ3694 Network 边双缩点+LCA+并查集

    辣鸡错误:把dfs和ldfs搞混...QAQ 题意:给定一个无向图,然后查询q次,求每次查询就在图上增加一条边,求剩余割边的个数. 先把边双缩点,然后预处理出LCA的倍增数组: 然后加边时,从u往上跳 ...

  3. H - Rescue the Princess ZOJ - 4097 (tarjan缩点+倍增lca)

    题目链接: H - Rescue the Princess  ZOJ - 4097 学习链接: zoj4097 Rescue the Princess无向图缩点有重边+lca - lhc..._博客园 ...

  4. Day10 - A - Rescue the Princess ZOJ - 4097

    Princess Cjb is caught by Heltion again! Her knights Little Sub and Little Potato are going to Helti ...

  5. sdut 2603:Rescue The Princess(第四届山东省省赛原题,计算几何,向量旋转 + 向量交点)

    Rescue The Princess Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 Several days ago, a b ...

  6. 山东省第四届acm.Rescue The Princess(数学推导)

    Rescue The Princess Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 412  Solved: 168 [Submit][Status ...

  7. 计算几何 2013年山东省赛 A Rescue The Princess

    题目传送门 /* 已知一向量为(x , y) 则将它旋转θ后的坐标为(x*cosθ- y * sinθ , y*cosθ + x * sinθ) 应用到本题,x变为(xb - xa), y变为(yb ...

  8. sdutoj 2603 Rescue The Princess

    http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2603 Rescue The Princess ...

  9. SDUT 2603:Rescue The Princess

    Rescue The Princess Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 Several days ago, a b ...

随机推荐

  1. 深入理解java虚拟机---读书笔记

    第一章 走近java 1. java 技术体系: java 程序设计语言 各种硬件平台上的java虚拟机 class 文件格式 java API 类库 来自商业机构或者开源机构的第三方java类库 j ...

  2. vue文字向上滚动

    <template> <vue-seamless-scroll :data="listData" :class-option="optionHover& ...

  3. StormUI各参数详解

    参考:http://www.malinga.me/reading-and-understanding-the-storm-ui-storm-ui-explained/  

  4. 修改Ubuntu屏幕的分辨率

      最近重新装了一下环境,用vnc连接服务器,发现分辨率过低,于是查了一下如何修改分辨率,将其调高.   编辑/etc/default/grub 搜索"#GRUB_GFXMODE=640x4 ...

  5. [转帖]2019-03-26 发布 深入理解 MySQL ——锁、事务与并发控制

    深入理解 MySQL ——锁.事务与并发控制 https://segmentfault.com/a/1190000018658828 太长了 没看完.. 数据库 并发  mysql 639 次阅读   ...

  6. 并发一:Java内存模型和Volatile

    并发一:Java内存模型和Volatile 一.Java内存模型(JMM) Java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和在内存中取出变量的底层细节,是围绕着 ...

  7. Photon Server 实现注册与登录(四) --- 服务端响应登陆和注册

    前面已经整理过了服务端代码,MyGameServer.cs 和 ClientPeer.cs 对请求和响应进行了拆分.接下来处理对前端的响应 一.响应登陆请求 之前整理中,响应前端请求主要在类Clien ...

  8. linux下shell 脚本 中windows换行符换成linux换行符

    sed -i 's/\r//' filename window下默认是 \r\n linux下是\n unix下是\r

  9. User space(用户空间) 与 Kernel space(内核空间)

    出处: User space 与 Kernel space (整理)用户空间_内核空间以及内存映射 学习 Linux 时,经常可以看到两个词:User space(用户空间)和 Kernel spac ...

  10. javascript常用内置对象——Array对象

    Array对象: 创建 Array 对象的语法: new Array(); new Array(元素个数); new Array(element0, element1, ..., elementn); ...