传送门
解析:
换根支配树?不要想了,你要是明白支配怎么建的你就知道这玩意不存在换根的
显然在无向图上除了起点终点以外的必经点就是割点。
显然我们就是询问路径上割点个数。
建立广义圆方树,显然路径上的所有圆点就是割点。
相当于询问圆方树路径上圆点个数。
这个嘛。。。怎么开心怎么玩是吧。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<20|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline int getint(){
re char c;
while(!isdigit(c=gc()));re int num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
}
using namespace IO;
using std::cout;
using std::cerr;
cs int N=5e5+5;;
int n,m,q;
int ext;
namespace Tree{
static cs int N=::N<<1;
std::vector<int> G[N];
inline void addedge(int u,int v){
G[u].push_back(v);
G[v].push_back(u);
}
int fa[N],dep[N],top[N],siz[N],son[N];
void dfs1(int u){
siz[u]=1;
for(int &v:G[u])if(v!=fa[u]){
fa[v]=u;
dep[v]=dep[u]+1;
dfs1(v);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
void dfs2(int u){
if(son[u]){
top[son[u]]=top[u];
dfs2(son[u]);
}
else return ;
for(int &v:G[u])if(v!=fa[u]&&v!=son[u]){
top[v]=v;
dfs2(v);
}
}
inline int LCA(int u,int v){
while(top[u]!=top[v])dep[top[u]]<dep[top[v]]?v=fa[top[v]]:u=fa[top[u]];
return dep[u]>dep[v]?v:u;
}
inline void build(){dfs1(1),top[1]=1,dfs2(1);}
inline int query(int u,int v){
int p=LCA(u,v);
return (dep[u]+dep[v]-dep[p]*2)/2+1;
}
}
namespace Graph{
static cs int N=::N;
std::vector<int> G[N];
inline void addedge(int u,int v){
G[u].push_back(v);
G[v].push_back(u);
}
int dfn[N],low[N],dfs_clock;
int sta[N],top;
void tarjan(int u){
dfn[u]=low[u]=++dfs_clock;
sta[++top]=u;
for(int &v:G[u]){
if(!dfn[v]){
tarjan(v);
low[u]=std::min(low[u],low[v]);
if(low[v]>=dfn[u]){
Tree::addedge(++ext,u);
int x;
do{
x=sta[top--];
Tree::addedge(x,ext);
}while(x!=v);
}
}
else low[u]=std::min(low[u],dfn[v]);
}
}
}
signed main(){
ext=n=getint(),m=getint();
for(int re i=1;i<=m;++i)Graph::addedge(getint(),getint());
Graph::tarjan(1);
Tree::build();
q=getint();
while(q--)cout<<Tree::query(getint(),getint())<<"\n";
return 0;
}