题目链接

可能是除了《概率论》的最水的黑题了吧

用\(Tarjan\)缩点(点双联通分量),然后就是树上两点之间的距离了,跑\(LCA\)就好了。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int s; char ch;
inline int read(){
s = 0; ch = getchar();
while(ch < '0' || ch > '9') ch = getchar();
while(ch >= '0' && ch <= '9') { s = s * 10 + ch - '0'; ch = getchar(); }
return s;
}
const int MAXN = 10010;
const int MAXM = 50010;
int dfn[MAXN], low[MAXN], id, bridge[MAXM << 1], dcc, belong[MAXN], top, vis[MAXN];
int n, m, a, b, head[MAXN], num = 1, f[MAXN][20], dep[MAXN], t, stack[MAXN];
struct Edge{
int from, next, to;
}e[MAXM << 2];
inline void Add(int from, int to){
e[++num].to = to; e[num].from = from; e[num].next = head[from]; head[from] = num;
e[++num].to = from; e[num].from = to; e[num].next = head[to]; head[to] = num;
}
void Tarjan(int u, int fa){
dfn[u] = low[u] = ++id; stack[++top] = u; vis[u] = 1;
for(int i = head[u]; i; i = e[i].next)
if(e[i].to != fa)
if(!dfn[e[i].to]){
Tarjan(e[i].to, u);
low[u] = min(low[u], low[e[i].to]);
}
else if(vis[e[i].to])
low[u] = min(low[u], dfn[e[i].to]);
if(dfn[u] == low[u]){
++dcc;
do
belong[stack[top]] = dcc;
while(stack[top--] != u);
}
}
void getDF(int u, int fa){
f[u][0] = fa; dep[u] = dep[fa] + 1;
for(int i = head[u]; i; i = e[i].next)
if(e[i].to != fa)
getDF(e[i].to, u);
}
int LCA(int u, int v){
if(dep[u] < dep[v]) swap(u, v);
int cha = dep[u] - dep[v];
if(cha)
for(int i = 0; i <= 18; ++i)
if((cha >> i) & 1)
u = f[u][i];
if(u != v){
for(int i = 18; ~i; --i)
if(f[u][i] != f[v][i])
u = f[u][i], v = f[v][i];
return f[u][0];
}
return u;
}
int dis(int u, int v){
return dep[u] + dep[v] - (dep[LCA(u, v)] << 1) + 1;
}
void print(int x){
if(x > 1) print(x >> 1);
printf("%d", x & 1);
}
int main(){
n = read(); m = read();
for(int i = 1; i <= m; ++i)
Add(read(), read());
for(int i = 1; i <= n; ++i)
if(!dfn[i])
Tarjan(i, 0);
memset(head, 0, sizeof head);
int tmp = num;
for(int i = 2; i <= tmp; i += 2)
if(belong[e[i].from] != belong[e[i].to])
Add(belong[e[i].from], belong[e[i].to]);
getDF(1, 0);
for(int j = 1; j <= 18; ++j)
for(int i = 1; i <= dcc; ++i)
f[i][j] = f[f[i][j - 1]][j - 1];
t = read();
while(t--) print(dis(belong[read()], belong[read()])), puts("");
return 0;
}

【洛谷 P2783】 有机化学之神偶尔会做作弊 (双联通分量)的更多相关文章

  1. 洛谷 P2783 有机化学之神偶尔会做作弊 解题报告

    P2783 有机化学之神偶尔会做作弊 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 有一天他一边搓炉石一边监考,而你作为一个信息竞赛的大神也来凑热闹. 然而你的化竞基友却向你求助了. &quo ...

  2. 洛谷 P2783 有机化学之神偶尔会做作弊(Tarjan,LCA)

    题目背景 LS中学化学竞赛组教练是一个酷爱炉石的人. 有一天他一边搓炉石一边监考,而你作为一个信息竞赛的大神也来凑热闹. 然而你的化竞基友却向你求助了. “第1354题怎么做”<--手语 他问道 ...

  3. [洛谷P2783]有机化学之神偶尔会做作弊

    第一次做出来黑题祭 虽然感觉难度其实并不到黑题的难度 题解: 其实这道题并没用什么特别的知识,只是Tarjan求双联通分量和LCA的结合. 所以,我们可以很显然的发现(如此恶劣的词汇,逃 这道题其实就 ...

  4. 【题解】Luogu P2783 有机化学之神偶尔会做作弊

    原题链接:P2783 有机化学之神偶尔会做作弊 一看,是黑题,太毒瘤了,不写 什么单链??! 只会画有机化学中正六边形的我觉得这样不行QAQ(我才初二) 当然,题目也给你了详细的解释 实际呢,这道题先 ...

  5. 洛谷P2783 有机化学之神偶尔会作弊

    题目传送门 啦啦啦,发个文纪念一下第一道在洛谷上A的黑题,一次性就过真是无比舒服-(虽然某些大佬说这题有点水……)题目其实思路不难,Tarjan缩点+LCA,不过因为是无向边,所以在Tarjan的时候 ...

  6. luogu P2783 有机化学之神偶尔会做作弊 |Tarjan+LCA

    题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 有一天他一边搓炉石一边监考,而你作为一个信息竞赛的大神也来凑热闹. 然而你的化竞基友却向你求助了. "第1354题怎么做"&l ...

  7. LuoGu P2783 有机化学之神偶尔会做作弊

    题目传送门 人生第一道黑题呢,虽然这题是黑题中的水题并且我调了一整节课,但是我还是很兴奋啊.毕竟人生第一道黑题啊 这个题根据题意,先把整个图进行tarjan缩点,建出一棵树,对于每一组询问,两点之间的 ...

  8. Tarjan+LCA【洛谷P2783】 有机化学之神偶尔会做作弊

    [洛谷P2783] 有机化学之神偶尔会做作弊 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 有一天他一边搓炉石一边监考,而你作为一个信息竞赛的大神也来凑热闹. 然而你的化竞基友却向你求助了. ...

  9. [luogu2783] 有机化学之神偶尔会做作弊

    题目链接 洛谷. Solution 边双缩点然后\(lca\)跑\(dis\)就好了. 注意这里是边双,不知道为啥所有题解都说的是点双. 边双是定义在点上的,即每个点只属于一个边双:点双是定义在边上的 ...

随机推荐

  1. 求gcd(最大公因数),lcm(最小公倍数)模板

    gcd(最大公因数),lcm(最小公倍数) #include<iostream> using namespace std; int gcd(int a,int b)//辗转相除法(欧几里德 ...

  2. python-网易云简单爬虫

    一.准备工作 1.使用python3.6和pycharm 2.使用的模块 tkinter .requests .beautifulSoup.getpass.os 3.网易云的榜单页面地址 https: ...

  3. PAT 1052 卖个萌

    https://pintia.cn/problem-sets/994805260223102976/problems/994805273883951104 萌萌哒表情符号通常由“手”.“眼”.“口”三 ...

  4. 【Docker 命令】- ps命令

    docker ps : 列出容器 语法 docker ps [OPTIONS] OPTIONS说明: -a:显示所有的容器,包括未运行的. -f:根据条件过滤显示的内容. --format :指定返回 ...

  5. vc6.0批量加注释

    MATLAB批量加注释的方法非常简单明了,加注释是ctrl+R,去注释是ctrl+T 然后在VC中我对一条一条加注释的方法非常烦恼,我想也许会有简单的方法可以批量家注释.果然,先贴代码 '------ ...

  6. [C/C++] C++类对象创建问题

    CSomething a();// 没有创建对象,这里不是使用默认构造函数,而是定义了一个函数,在C++ Primer393页中有说明. CSomething b(2);//使用一个参数的构造函数,创 ...

  7. 第一篇:python基础_1

    本篇内容 Python介绍 安装 第一个程序(hello,world) 变量 用户输入(input) 数据类型 数据运算 if判断 break和continue的区别 while 循环 一. Pyth ...

  8. 【bzoj3297】[USACO2011 Open]forgot STL+dp

    题目描述 发生了这么多,贝茜已经忘记了她cowtube密码.然而,她记得一些有用的信息. 首先,她记得她的密码(记为变量P)长度为L(1 <= L<=1,000)字符串,并可以被分成 一个 ...

  9. Luogu4899 IOI2018狼人(kruskal重构树+主席树)

    可以发现询问的即是“由起点开始‘只经过编号大于等于l的点’所形成的连通块”与“由终点开始‘只经过编号小于等于r的点’所形成的连通块”是否有交集.于是建出重构树,就可以知道每个询问的连通情况了.现在要知 ...

  10. Python 源码剖析(四)【LIST对象】

    四.LIST对象 1.PyListObject对象 2.PyListObject的创建与维护 3.PyListObject 对象缓冲池 4.Hack PyListObject 1.PyListObje ...