-图论-强连通分量-LCA- [洛谷 P2783]有机化学之神偶尔会做作弊

题目背景

XS中学化学竞赛组教练是一个酷爱炉石的人。

有一天他一边搓炉石一边监考,而你作为一个信息竞赛的大神也来凑热闹。

然而你的化竞基友却向你求助了。

“第1354题怎么做”<—手语 他问道。

题目描述

你翻到那一题:给定一个烃,只含有单键(给初中生的一个理解性解释:就是一堆碳用横线连起来,横线都是单条的)。

然后炎魔之王拉格纳罗斯用他的火焰净化了一切环(???)。所有的环状碳都变成了一个碳。如图所示。

然后指定多组碳,求出它们之间总共有多少碳。如图所示(和上图没有关系)。


但是因为在考试,所以你只能把这个答案用手语告诉你的基友。你决定用二进制来表示最后的答案。如图所示(不要在意,和题目没有什么没关系)。

输入格式

第一行两个整数n,m.表示有n个点,m根键

接下来m行每行两个整数u,v表示u号碳和v号碳有一根键

接下来一个整数tot表示询问次数

接下来tot行每行两个整数,a,b表示询问的两个碳的编号

输出格式

共tot行

每行一个二进制数

输入样例

3 2
1 2
2 3
2
1 2
2 3

输出样例

10
10

Solution

先进行无向图的缩点,然后再用倍增求LCA就可以了

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 100010
#define LOG 30
namespace STman {
inline char gc(){
#ifdef ONLINE_JUDGE
static char now[1 << 16], *S, *T;
if (T == S) {T = (S = now) + fread(now, 1, 1 << 16, stdin); if (T == S) return EOF;}
return *S++;
#else
return getchar();
#endif
}
template <typename Tp>
inline void read(Tp &x) {
Tp f = 1;x = 0;
char k = gc();
while (k < '0' || k > '9') {if (k == '-') f = -1;k = gc();}
while (k >= '0' && k <= '9') {x = x * 10 + k - '0';k = gc();}
x = x * f;
}
template <typename Tp>
inline void write(Tp x) {
if (x < 0) putchar('-') , x = -x;
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
template <typename Tp>
inline Tp max(Tp a , Tp b) {
if (a > b) return a;
else return b;
}
template <typename Tp>
inline Tp min(Tp a , Tp b) {
if (a < b) return a;
else return b;
}
template <typename Tp>
inline void swap(Tp &a , Tp &b) {
Tp t = a;
a = b;
b = t;
}
template <typename Tp>
inline Tp abs(Tp &a) {
if (a < 0) return -a;
else return a;
}
inline void sp() {
putchar(32);
}
inline void et() {
putchar(10);
}
}
using namespace STman;
struct Edge {
int v, nx;
}e[MAXN];
int head[MAXN], ecnt, dfn[MAXN], in[MAXN], st[MAXN], q, f, g;
int top, num, n, m, x[MAXN], y[MAXN], low[MAXN], tim;
int anc[MAXN << 1][LOG], dep[MAXN << 1], len;
bool vis[MAXN], a[MAXN];
void add(int f, int t) {
e[++ecnt] = (Edge) {t, head[f]};
head[f] = ecnt;
}
void tarjan(int u, int fa) {
dfn[u] = low[u] = ++tim;
st[++top] = u;
for (int i = head[u]; i; i = e[i].nx) {
int v = e[i].v;
if (v == fa) continue;
if (!dfn[v]) {
tarjan(v, u);
low[u] = min(low[u], low[v]);
}
else low[u] = min(low[u], dfn[v]);
}
if (low[u] == dfn[u]) {
int v;
num++;
do {
v = st[top--];
in[v] = num;
} while (u != v);
}
}
void dfs(int u, int p, int d) {
anc[u][0] = p;
dep[u] = d;
for (int i = head[u]; i; i = e[i].nx) {
int to = e[i].v;
if (to == p) continue;
dfs(to, u, d + 1);
}
}
inline void init(int r, int n) {
dfs(r, 0, 1);
for (int j = 1; j < LOG; j++) {
for (int i = 1; i <= n; i++) {
anc[i][j] = anc[anc[i][j - 1]][j - 1];
}
}
}
inline int LCA(int x, int y) {
if (dep[x] < dep[y]) std::swap(x , y);
int h = dep[x] - dep[y];
for (int i = 0; h > 0; i++) {
if (h & 1) x = anc[x][i];
h >>= 1;
}
if (x == y) return x;
for (int i = LOG - 1; i >= 0; i--) {
if (anc[x][i] != anc[y][i]) {
x = anc[x][i];
y = anc[y][i];
}
}
return anc[x][0];
}
int main() {
read(n), read(m);
for (int i = 1; i <= m; i++) {
read(x[i]), read(y[i]);
add(x[i], y[i]);
add(y[i], x[i]);
}
for (int i = 1; i <= n; i++) {
if (!dfn[i]) tarjan(i, -1);
}
memset(vis, 0, sizeof(vis));
memset(head, 0, sizeof(head));
memset(e, 0, sizeof(e));
ecnt = 0;
for (int i = 1; i <= m; i++) {
if (in[x[i]] != in[y[i]]) {
add(in[x[i]], in[y[i]]);
add(in[y[i]], in[x[i]]);
}
}
init(1, num);
read(q);
for (int i = 1; i <= q; i++) {
read(f), read(g);
int ws = 0;
f = in[f];
g = in[g];
int lca = dep[f] + dep[g] - 2 * dep[LCA(f, g)] + 1;
while (lca) {
a[++ws] = lca % 2;
lca /= 2;
}
for (int j = ws; j >= 1; j--) {
write(a[j]);
}
et();
}
}
文章作者: RiverFun
文章链接: https://stevebraveman.github.io/blog/2018/12/10/48/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 RiverFun

评论