RT,这题是不是可以升蓝?我菜大佬别喷。感觉又有tarjan又有LCA的,更何况还要判断写边双还是点双,本人码了100多行还MLE了,so请求升蓝QAQ。
//自认为码风清新良好
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+10;
int n,m,s,u[N],v[N],a,b;
struct node{
int nxt,to;
}e[N];
int h[N],cnt;
void add(int u,int v){
e[++cnt].nxt=h[u];
e[cnt].to=v;
h[u]=cnt;
}
struct Node{
int nxt2,to2;
}e2[N];
int h2[N],cnt2;
void add2(int u,int v){
e2[++cnt].nxt2=h2[u];
e2[cnt].to2=v;
h2[u]=cnt2;
}
bool ins[N];
int dfn[N],low[N],size[N];
int tot,idx,st[N],top,bel[N];
void tarjan(int u,int fa){
low[u]=dfn[u]=++tot;
st[++top]=u;
ins[u]=1;
for(int i=h2[u];i;i=e2[i].nxt2){
int v=e2[i].to2;
if(v==fa)continue;
if(!dfn[v]){
tarjan(v,u);
low[u]=min(low[u],low[v]);
}
else if(ins[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
int v;
++idx;
do{
v=st[top--];
bel[v]=idx;
ins[v]=0;
size[idx]++;
}while(v!=u);
}
}
int d[N],anc[N][20];
void init(){
for(int j=1;j<=18;j++){
for(int i=1;i<=n;i++){
anc[i][j]=anc[anc[i][j-1]][j-1];
}
}
}
void dfs(int u,int fa){
for(int i=h[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==fa)continue;
anc[v][0]=u;
d[v]=d[u]+1;
dfs(v,u);
}
}
int lca(int u,int v){
if(d[u]<d[v])swap(u,v);
for(int i=18;i>=0;i--){
if(d[anc[u][i]]>=d[v]){
u=anc[u][i];
}
}
if(u==v)return u;
for(int i=18;i>=0;i--){
if(anc[u][i]!=anc[v][i]){
u=anc[u][i];
v=anc[v][i];
}
}
return anc[u][0];
}
void write(int x){
if(!x)return;
write(x>>1);
printf("%d",x&1);
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>u[i]>>v[i];
add2(u[i],v[i]);
add2(v[i],u[i]);
}
for(int i=1;i<=n;i++){
if(!dfn[i])tarjan(i,i);
}
for(int i=1;i<=m;i++){
int from=bel[u[i]],to=bel[v[i]];
if(from!=to){
add(from,to);
add(to,from);
}
}
dfs(1,0);
init();
cin>>s;
while(s--){
cin>>a>>b;
a=bel[a];b=bel[b];
write(d[a]+d[b]-2*d[lca(a,b)]+1);
cout<<endl;
}
return 0;
}
求调!