CodeForces 97 E. Leaders(点双连通分量 + 倍增)
题意
给你一个有 \(n\) 个点 \(m\) 条边的无向图,有 \(q\) 次询问,每次询问两个点 \(u, v\) 之间是否存在长度为奇数的简单路径。
\(1 \le n, m, q \le 10^5\)
题解
显然我们可以对于每个联通块单独处理,如果 \(u, v\) 不联通显然就不存在这条路。
然后对于每个联通块,首先随便弄一颗生成树。
- 如果这 \(u \to v\) 在树上的路径长就为奇数,显然是可以的,这个可以预处理深度就行了。
- 否则,\(u \to v\) 在树上的路径的边,只要存在一条边属于一个奇环就行了。
然后我们只要求出每条边是否属于一个奇环就行了。
单是求环的话,我们显然可以用求点双联通分量的方法来求的,求奇环需要用到下面的一个性质。
一个点双连通分量中要么每条边都在至少一个奇环上, 要么没有奇环.
这个证明是很显然的,可以自己手动画图理解。这个性质可以记住,到时候或许有用。
所以如果点双中存在一条边属于奇环,那么所有边都是在奇环上。
判断奇环可以直接判这个点连的两条边奇偶性是否相同,如果相同那么就是奇环了。
然后我们需要查询两个点的路径上是否存在一条边属于奇环,这个可以直接用树上差分做。
然后对于之前记一条边是否在奇环上,需要把这个点双中除了点双中最上面的那个点 \(u\) 全部标成 \(1\) 。
也就是我们都标到儿子上就行了。
实现起来就是 (cnt[u] + cnt[v] - 2 * cnt[Get_Lca(u, v)]) > 0
,cnt
为到根路径上标号的前缀和,用倍增求 Lca
就行了。
总结
多找性质,多思考,多记性质。
代码
具体实现看代码就行啦qwq 注意此处点双要存边才行,还要注意一些小细节。
#include <bits/stdc++.h>
#define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define debug(x) cout << #x << ": " << x << endl
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)
#define fir first
#define sec second
#define mp make_pair
using namespace std;
typedef pair<int, int> PII;
inline bool chkmin(int &a, int b) {return b < a ? a = b, 1 : 0;}
inline bool chkmax(int &a, int b) {return b > a ? a = b, 1 : 0;}
inline int read() {
int x = 0, fh = 1; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') fh = -1;
for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
return x * fh;
}
void File() {
#ifdef zjp_shadow
freopen ("E.in", "r", stdin);
freopen ("E.out", "w", stdout);
#endif
}
const int N = 1e5 + 1e3, M = N << 1;
int n, m, Logn;
int anc[N][20], dep[N];
vector<int> G[N]; bitset<N> vis1, vis2; int id[N], version;
void Dfs_Init(int u, int fa = 0) {
id[u] = version; vis1[u] = true; dep[u] = dep[anc[u][0] = fa] + 1;
For (i, 1, Logn) anc[u][i] = anc[anc[u][i - 1]][i - 1];
for (int v : G[u]) if (!vis1[v]) Dfs_Init(v, u);
}
int dfn[N], lowlink[N], cnt[N];
PII sta[M]; int top = 0;
void Tarjan(int u, int fa = 0) {
static int clk = 0;
dfn[u] = lowlink[u] = ++ clk;
for (int v : G[u]) if (v != fa && dfn[v] < dfn[u]) {
sta[++ top] = mp(u, v);
if (!dfn[v]) {
Tarjan(v, u);
chkmin(lowlink[u], lowlink[v]);
if (lowlink[v] >= dfn[u]) {
int tmp = top, x, y, flag = 0;
do {
x = sta[top].fir; y = sta[top --].sec;
if ((dep[x] & 1) == (dep[y] & 1)) { flag = 1; break; }
} while (!(x == u && y == v));
if (!flag) continue ;
top = tmp;
do {
x = sta[top].fir; y = sta[top --].sec;
cnt[x] = cnt[y] = 1;
} while (!(x == u && y == v));
cnt[u] = 0;
}
} else chkmin(lowlink[u], dfn[v]);
}
}
void Dfs_Calc(int u, int fa = 0) {
cnt[u] += cnt[fa]; vis2[u] = true;
for (int v : G[u]) if (!vis2[v]) Dfs_Calc(v, u);
}
inline int Get_Lca(int x, int y) {
if (dep[x] < dep[y]) swap(x, y);
Fordown (i, Logn, 0)
if (dep[anc[x][i]] >= dep[y]) x = anc[x][i];
if (x == y) return x;
Fordown (i, Logn, 0)
if (anc[x][i] != anc[y][i]) x = anc[x][i], y = anc[y][i];
return anc[x][0];
}
inline bool Check(int u, int v) {
if (id[u] != id[v]) return false;
if ((dep[u] & 1) ^ (dep[v] & 1)) return true;
return (cnt[u] + cnt[v] - 2 * cnt[Get_Lca(u, v)]) > 0;
}
int main () {
File();
n = read(); m = read();
Logn = ceil(log2(n));
For (i, 1, m) {
int u = read(), v = read();
G[u].push_back(v); G[v].push_back(u);
}
For (i, 1, n) if (!dfn[i]) ++ version, Dfs_Init(i), Tarjan(i), Dfs_Calc(i);
int q = read();
For (i, 1, q) {
int u = read(), v = read();
puts(Check(u, v) ? "Yes" : "No");
}
return 0;
}
CodeForces 97 E. Leaders(点双连通分量 + 倍增)的更多相关文章
- [Codeforces 555E]Case of Computer Network(Tarjan求边-双连通分量+树上差分)
[Codeforces 555E]Case of Computer Network(Tarjan求边-双连通分量+树上差分) 题面 给出一个无向图,以及q条有向路径.问是否存在一种给边定向的方案,使得 ...
- codeforces 962F.simple cycle(tarjan/点双连通分量)
题目连接:http://codeforces.com/contest/962/problem/F 题目大意是定义一个simple cycle为从一个节点开始绕环走一遍能经过simple cycle内任 ...
- Codeforces 521E - Cycling City(点双连通分量+分类讨论)
Codeforces 题面传送门 & 洛谷题面传送门 大家都是暴力找生成树然后跳路径,代码不到 50 行(暴论)的一说--好,那本蒟蒻决定提供一种代码 150 行,但复杂度也是线性的分类讨论做 ...
- Simple Cycles Edges CodeForces - 962F(点双连通分量)
题意: 求出简单环的所有边,简单环即为边在一个环内 解析: 求出点双连通分量,如果一个连通分量的点数和边数相等,则为一个简单环 点双连通分量 任意两个点都至少存在两条点不重复的路径 即任意两条边都 ...
- 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 ...
- POJ2942 Knights of the Round Table[点双连通分量|二分图染色|补图]
Knights of the Round Table Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 12439 Acce ...
- 【Codefoces487E/UOJ#30】Tourists Tarjan 点双连通分量 + 树链剖分
E. Tourists time limit per test: 2 seconds memory limit per test: 256 megabytes input: standard inpu ...
- 【BZOJ-2730】矿场搭建 Tarjan 双连通分量
2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1602 Solved: 751[Submit][Statu ...
- hihoCoder 1184 连通性二·边的双连通分量
#1184 : 连通性二·边的双连通分量 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在基本的网络搭建完成后,学校为了方便管理还需要对所有的服务器进行编组,网络所的老 ...
随机推荐
- centos7 安装phpmyadmin
1.先安装epel,不然安装pgpmyadmin时会出现找不到包. yum install epel-release rpm -ivh http://rpms.famillecollet.com/en ...
- Day1 Numerical simulation of optical wave propagation之标量衍射理论基本原理(一)
<Numerical simulation of optical wave propagation>内容 1. 介绍光波传输的基础理论.离散采样方法.基于MATLAB平台的编码实例以及具 ...
- Python之操作MySQL数据库
一.操作步骤 1.导入pymysql模块 2.建立连接(ip.用户名.密码.数据库名.端口号.字符集.(自动提交参数)) 3.建立游标 4.执行sql语句 (4.需要提交的提交) 5.关闭游标 6 ...
- 学习yii2.0——行为
学习yii框架的行为之前,需要先了解yii的事件,可以参考这篇博客: 怎么理解行为 yii框架的行为有点类似于trait,可以有个大体的概念: 1.有一个类A,包含一些属性和方法,很普通的一个类A. ...
- semantic-ui 图标
semantic-ui提供了很多的图标,基本常用的在官网上面都能找到.要想记住这么多图标是不可能的,但是也是有简便方法记忆. 首先,图标其实和按钮的区别基本没有,要说有的话,也就是基础样式的大小不同吧 ...
- 50分钟学会Laravel 50个小技巧(基于laravel5.2,仅供参考)
转载请注明:转载自 Yuansir-web菜鸟 | LAMP学习笔记 本文链接地址: 50分钟学会Laravel 50个小技巧 原文链接:< 50 Laravel Tricks in 50 Mi ...
- 转:win7下git凭据导致无法clone代码
win7下存在一个凭据管理的情况,如果旧凭据没有删除,用新账户是无法clone代码的. https://blog.csdn.net/qq_34665539/article/details/804082 ...
- png8、16、24、32位的区别
我们都知道一张图片可以保存为很多种不同的格式,比如bmp/png/jpeg/gif等等.这个是从文件格式的角度看,我们抛开文件格式,看图片本身,我们可以分为8位, 16位, 24位, 32位等. 单击 ...
- thymeleaf 引入公共html注意事项
详细连接https://blog.csdn.net/u010260737/article/details/83616998 每个页面都会用到分页.html或者头部.html.尾部.html,在其他页面 ...
- python之tips(三)--为什么Python有相同的不可变对象id不同?
参考 : https://www.jianshu.com/p/0f6f0db0ce8f