P4320 道路相遇
考虑建出圆方树。
对于任意两个点,其路径中必须要经过的点就是这两个点对应的圆方树中点的路径之间圆点数量。也就是割点数量。
于是 LCA 处理即可。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <vector>
using namespace std;
const int N = 1e6 + 5;
int dfn[N], low[N], idx, cnt;
int n, m, q;
vector<int> G[N], NG[N];
int sum[N];
int stk[N], top;
void tarjan(int u)
{
dfn[u] = low[u] = ++idx;
stk[++top] = u;
for (int j : G[u])
{
if (!dfn[j])
{
tarjan(j);
low[u] = min(low[u], low[j]);
if (dfn[u] == low[j])
{
cnt++;
for (int y = 0; y != j; top--)
{
y = stk[top];
NG[y].emplace_back(cnt);
NG[cnt].emplace_back(y);
}
NG[cnt].emplace_back(u);
NG[u].emplace_back(cnt);
}
}
else
{
low[u] = min(low[u], dfn[j]);
}
}
}
void dfs(int u, int fa)
{
sum[u] = sum[fa] + (u <= n);
for (int j : NG[u])
{
if (j != fa)
{
dfs(j, u);
}
}
}
class TreeCut
{
public:
int id[N], top[N], sz[N], dep[N], fa[N], son[N], idx;
void dfs1(int u, int f)
{
dep[u] = dep[f] + 1;
fa[u] = f;
sz[u] = 1;
for (int j : NG[u])
{
if (j != f)
{
dfs1(j, u);
sz[u] += sz[j];
if (sz[son[u]] < sz[j]) son[u] = j;
}
}
}
void dfs2(int u, int tf)
{
id[u] = ++idx;
top[u] = tf;
if (!son[u]) return;
dfs2(son[u], tf);
for (int j : NG[u])
{
if (j != son[u] && j != fa[u])
{
dfs2(j, j);
}
}
}
void build()
{
dfs1(1, 1);
dfs2(1, 1);
}
int LCA(int u, int v)
{
while (top[u] ^ top[v])
{
if (dep[top[u]] < dep[top[v]]) swap(u, v);
u = fa[top[u]];
}
return (dep[u] < dep[v] ? u : v);
}
}tc;
int main()
{
scanf("%d%d", &n, &m);
cnt = n;
for (int i = 1; i <= m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
G[u].emplace_back(v);
G[v].emplace_back(u);
}
tarjan(1);
dfs(1, 1);
tc.build();
scanf("%d", &q);
while (q--)
{
int s, t;
scanf("%d%d", &s, &t);
int lca = tc.LCA(s, t);
printf("%d\n", sum[s] + sum[t] - 2 * sum[lca] + (lca <= n));
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】