洛谷P4320 道路相遇(LCA+圆方树)

题目链接:https://www.luogu.com.cn/problem/P4320

道路相遇

题目描述

在 H 国的小 w 决定到从城市 $u$ 到城市 $v$ 旅行,但是此时小 c 由于各种原因不在城市 $u$,但是小 c 决定到在中途与小 w 相遇

由于 H 国道路的原因,小 w 从城市 $u$ 到城市 $v$ 的路线不是固定的,为了合理分配时间,小 c 想知道从城市 $u$ 到城市 $v$ 有多少个城市小 w 一定会经过,特别地,$u, v$ 也必须被算进去,也就是说无论如何答案不会小于 2

由于各种特殊的原因,小 c 并不知道小 w 的起点和终点,但是小 c 知道小 w 的起点和终点只有 $q$ 种可能,所以对于这 $q$ 种可能,小 c 都想知道小 w 一定会经过的城市数

H 国所有的边都是无向边,两个城市之间最多只有一条道路直接相连,没有一条道路连接相同的一个城市

任何时候,H 国不存在城市 $u$ 和城市 $v$ 满足从 $u$ 无法到达 $v$

输入格式

第一行两个正整数 $n,m$,表示 H 国的城市数,以及道路数。

下面 $m$ 行,每行两个不同的正整数 $u, v$,表示城市 $u$ 到城市 $v$ 之间有一条边。

然后一行一个正整数 $q$。
接下来 $q$ 行,每行两个正整数 $u, v$ 表示小 w 旅行的一种可能的路线

输出格式

输出共 $q$ 行,每行一个正整数

样例 #1

样例输入 #1

5 6
1 2
1 3
2 3
3 4
4 5
3 5
1
1 5

样例输出 #1

3

提示

从城市 $1$ 到城市 $5$ 总共有 $4$ 种可能 :

$1 \to 2 \to 3 \to 4 \to 5$

$1 \to 2 \to 3 \to 5$

$1 \to 3 \to 4 \to 5$

$1 \to 3 \to 5$

可以发现小 w 总会经过城市 $1,3,5$,所以答案为 $3$

你可以认为小 w 不会经过相同的城市两次,当然,如果你认为可以经过相同的城市两次也不会影响答案

subtask1 : 15分,$m = 5, q = 50$

subtask2 : 15分,$n = 100, q = 5000$

subtask3 : 20分,$n = 3000, q = 5\times 10^5$

subtask4 : 20分,$n = 499999, q = 5 \times 10^5, m = n-1$

subtask5 : 30分,$n = q = 5 \times 10^5$

对于所有数据 : $1\leq n\leq 5 \times 10^5, 1\leq q\leq 5\times 10^5, 1\leq m\leq \min(\frac{n(n-1)}{2}, 10^6)$

 

代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<vector>
  4 #include<map>
  5 #include<queue>
  6 #include<set>
  7 #include<algorithm>
  8 #include<stack>
  9 #include<cmath>
 10 #include<cstring>
 11 #include<string>
 12 using namespace std;
 13 #define gc getchar()
 14 #define rd(x) read(x)
 15 #define el '\n'
 16 #define rep(i, a, n) for(int i = (a); i <= n; ++i)
 17 #define per(i, a, n) for(int i = (a); i >= n; --i)
 18 using ll = long long;
 19 using db = double;
 20 using ldb = long double;
 21 const int N = 500000 + 10;
 22 const int mod = 1e9 + 7;
 23 const int inf = 0x3f3f3f3f;
 24 
 25 template <typename _T>
 26 inline void read(_T& f) {
 27     f = 0; _T fu = 1; char c = gc;
 28     while (c < '0' || c > '9') { if (c == '-') { fu = -1; } c = gc; }
 29     while (c >= '0' && c <= '9') { f = (f << 3) + (f << 1) + (c & 15); c = gc; }
 30     f *= fu;
 31 }
 32 
 33 template <typename T>
 34 void print(T x) {
 35     if (x < 0) putchar('-'), x = -x;
 36     if (x < 10) putchar(x + 48);
 37     else print(x / 10), putchar(x % 10 + 48);
 38 }
 39 
 40 template <typename T>
 41 void print(T x, char t) {
 42     print(x); putchar(t);
 43 }
 44 
 45 int n, m;
 46 vector<int>G[N << 2];
 47 
 48 struct node {
 49     int to, w, next;
 50 }e[N << 2];
 51 int head[N << 2], tot;
 52 
 53 void add(int u, int v) {
 54     e[tot].to = v;
 55     //e[tot].w = w;
 56     e[tot].next = head[u];
 57     head[u] = tot++;
 58 }
 59 
 60 int dfn[N << 2], low[N << 2], dfc;
 61 int stk[N << 2], tp, bcc;
 62 
 63 void tarjan(int u) {
 64 
 65     dfn[u] = low[u] = ++dfc;
 66     stk[++tp] = u;
 67     for (int i = 0; i < (int)G[u].size(); i++) {
 68         int v = G[u][i];
 69         if (!dfn[v]) {
 70             tarjan(v);
 71             low[u] = min(low[u], low[v]);
 72             if (low[v] == dfn[u]) {
 73                 bcc++;
 74                 for (int x = 0; x != v; tp--) {
 75                     x = stk[tp];
 76                     add(x, bcc), add(bcc, x);
 77                 }
 78                 add(u, bcc), add(bcc, u);
 79             }
 80         }
 81         else low[u] = min(low[u], dfn[v]);
 82     }
 83 
 84 }
 85 
 86 int fa[N << 2][31], dep[N << 2];
 87 
 88 void dfs(int x, int pre) {
 89 
 90     fa[x][0] = pre;
 91     dep[x] = dep[pre] + 1;
 92     for (int i = 1; i <= 30; i++) {
 93         fa[x][i] = fa[fa[x][i - 1]][i - 1];
 94     }
 95     for (int i = head[x]; i + 1; i = e[i].next) {
 96         int to = e[i].to;
 97         if (to != pre) dfs(to, x);
 98     }
 99 
100 }
101 
102 int lca(int x, int y) {
103 
104     if (dep[x] < dep[y]) swap(x, y);
105     for (int i = 30; i >= 0; i--) {
106         if ((1 << i) <= dep[x] - dep[y]) x = fa[x][i];
107     }
108     if (x == y) return x;
109     for (int i = 30; i >= 0; i--) {
110         if (fa[x][i] != fa[y][i]) {
111             x = fa[x][i];
112             y = fa[y][i];
113         }
114     }
115 
116     return fa[x][0];
117 }
118 
119 int main() {
120 
121     ios::sync_with_stdio(false);
122     cin.tie(0), cout.tie(0);
123     memset(head, -1, sizeof(head));
124     cin >> n >> m;
125     bcc = n;
126     for (int i = 1; i <= m; i++) {
127         int u, v;
128         cin >> u >> v;
129         G[u].push_back(v);
130         G[v].push_back(u);
131     }
132     //cout << el;
133     tarjan(1);
134     /*for(int i = n + 1; i <= bcc; i++) {
135         for(int j = head[i]; j + 1; j = e[j].next) {
136             cout << i << ' ' << e[j].to << el;
137         }
138         //cout << el;
139     }
140     cout << el;*/
141     dfs(1, 1);
142     int q;
143     cin >> q;
144     for (; q; --q) {
145         int u, v;
146         cin >> u >> v;
147         int p = lca(u, v);
148         //cout << p << el;
149         int ans;
150         if (p > n) {
151             ans = (dep[u] - dep[p] + 1) / 2 + (dep[v] - dep[p] + 1) / 2;
152         }
153         else {
154             ans = (dep[u] - dep[p]) / 2 + (dep[v] - dep[p]) / 2 + 1;
155         }
156         cout << ans << el;
157     }
158 
159     return 0;
160 }

 

 
posted @ 2022-10-11 08:49  Keyzee  阅读(43)  评论(0编辑  收藏  举报