思路:
先用 T a r j a n Tarjan Tarjan對原圖進行一個縮點,然後建一個圖,然後處理一下樹上的點距,求一下 L c a Lca Lca即可
參考代碼:
/*
* @Author: vain
* @Date: 2020-08-26 11:58:46
* @LastEditTime: 2020-09-08 18:01:56
* @LastEditors: sueRimn
* @Description: In User Settings Edit
* @FilePath: \main\demo.cpp
*/
//#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
//#define ll long long
typedef unsigned long long ull;
const int N = 1e3 + 20;
const ll maxn = 1e5 + 20;
const ll mod = 1e9 + 7;
int head[maxn], stac[maxn], vis[maxn], depth[maxn], pre[maxn][32];
int dis[maxn], dfn[maxn], low[maxn], sg[maxn];
//typedef pair p;
//priority_queue, greater
> m;
//ll sum[maxn];
int max(int a, int b) {
return a > b ? a : b; }
ll min(ll a, ll b) {
return a < b ? a : b; }
ll gcd(ll a, ll b) {
return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) {
return a * b / gcd(a, b); }
void swap(ll &x, ll &y) {
x ^= y, y ^= x, x ^= y; }
map<string, ll> pll, che, mp;
int us[maxn], vs[maxn], cnt, top, ans, ti;
int lowbit(int x) {
return (x) & (-x); }
vector<int> fc;
//ull h[maxn], p[maxn];
const ull base = 13331;
//char s1[maxn];
ll ksm(ll a, ll b)
{
ll res = 1;
while (b)
{
if (b & 1)
res = a * res;
b >>= 1;
a = a * a;
}
return res;
}
struct node
{
int v, nex;
} edge[maxn << 1];
void add(int u, int v)
{
edge[cnt].v = v, edge[cnt].nex = head[u];
head[u] = cnt++;
}
void tarjan(int u, int fa)
{
low[u] = dfn[u] = ++ti;
stac[top++] = u, vis[u] = 1;
for (int i = head[u]; ~i; i = edge[i].nex)
{
int v = edge[i].v;
if (v != fa)
{
if (!dfn[v])
{
tarjan(v, u);
low[u] = min(low[v], low[u]);
}
else if (vis[v])
{
low[u] = min(low[u], dfn[v]);
}
}
}
if (low[u] == dfn[u])
{
ans++;
while (top && stac[top] != u)
{
--top;
int x = stac[top];
sg[x] = ans, vis[x] = 0;
}
}
}
void dfs(int u, int fa) //求深度
{
depth[u] = depth[fa] + 1;
pre[u][0] = fa;
for (int i = 1; (1 << i) <= depth[u]; i++)
pre[u][i] = pre[pre[u][i - 1]][i - 1];
for (int i = head[u]; ~i; i = edge[i].nex)
{
int v = edge[i].v;
if (fa != v)
{
dis[v] = dis[u] + 1;
dfs(v, u);
}
}
}
int lca(int u, int v)
{
if (depth[u] < depth[v])
swap(u, v); //让u的深度大
int i = -1, j;
while ((1 << (i + 1)) <= depth[u]) //从u跨到根节点的跨度
i++;
for (j = i; j >= 0; j--) //同一水平
{
if (depth[u] - (1 << j) >= depth[v])
{
u = pre[u][j];
}
}
if (u == v)
{
return u;
}
for (j = i; j >= 0; j--)
{
if (pre[u][j] != pre[v][j])
{
u = pre[u][j];
v = pre[v][j];
}
}
return pre[u][0];
}
void solv(int x)
{
bool ok = false;
for (int i = 31; ~i; i--)
{
if ((x >> i) & 1)
{
cout << 1;
ok = true;
}
else if (ok)
{
cout << 0;
}
}
cout << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
srand(time(NULL));
//cout << ksm(2, 20) << endl;
int n, m, u, v, q;
// cin >> t;zz
// while (t--)
// {
// }
memset(head, -1, sizeof head);
cin >> n >> m;
for (int i = 0; i < m; i++)
cin >> u >> v, add(u, v), add(v, u), us[i] = u, vs[i] = v;
for (int i = 1; i <= n; i++)
{
if (!dfn[i])
tarjan(i, 0);
}
cnt = 0;
memset(head, -1, sizeof head);
for (int i = 0; i < m; i++)
{
if (sg[us[i]] != sg[vs[i]])
add(sg[us[i]], sg[vs[i]]), add(sg[vs[i]], sg[us[i]]);
}
dis[sg[1]] = 1;
dfs(sg[1], 0);
cin >> q;
while (q--)
{
cin >> u >> v;
int Lca = lca(sg[u], sg[v]);
int ia = dis[sg[u]] + dis[sg[v]] - 2 * dis[Lca] + 1;
solv(ia);
}
}