【luogu2783】 有机化学之神偶尔会做作弊 [tarjan 缩点][LCA]
缩点 然后LCA x,y两点之间的距离为dep[x]+dep[y]-2dep[lca]+1
死于各种缩点之后忘记用bl
#include<bits/stdc++.h> using namespace std; #define ll long long const int N=10000+50,M=50000+50,inf=0x3f3f3f3f; int n,m,q,ans=0,f[N][25],dep[N]; int idx=0,Bcnt=0,dfn[N],low[N],bl[N]; bool inst[N]; stack<int>s; template<class t>void rd(t &x){ x=0;int w=0;char ch=0; while(!isdigit(ch)) w|=ch=='-',ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); x=w?-x:x; } int head[N],tot=0; struct edge{int u,v,nxt;}e[M<<1],e2[M<<1]; void add(int u,int v){ e[++tot]=(edge){u,v,head[u]};head[u]=tot; } void tarjan(int u,int fa){ dfn[u]=low[u]=++idx; s.push(u),inst[u]=1; for(int i=head[u],v;i;i=e[i].nxt){ v=e[i].v; if(v!=fa){ if(!dfn[v]) tarjan(v,u),low[u]=min(low[u],low[v]); else if(inst[v]&&low[u]>dfn[v]) low[u]=dfn[v]; } } if(low[u]==dfn[u]){ ++Bcnt; int v; do{ v=s.top(),s.pop(); bl[v]=Bcnt,inst[v]=0; }while(u!=v); } } int head2[N],tot2=0; void add2(int u,int v){ e2[++tot2]=(edge){u,v,head2[u]};head2[u]=tot2; } void dfs(int u,int fa){ dep[u]=dep[fa]+1; f[u][0]=fa; for(int i=1;i<=20;++i){ if(dep[u]<(1<<i)) break; f[u][i]=f[f[u][i-1]][i-1]; } for(int i=head2[u];i;i=e2[i].nxt){ if(e2[i].v==fa) continue; dfs(e2[i].v,u); } } int LCA(int a,int b){ if(dep[a]>dep[b]) swap(a,b); for(int i=20;i>=0;--i){ if(dep[f[b][i]]<dep[a]) continue; b=f[b][i]; } if(b==a) return a; for(int i=20;i>=0;--i){ if(f[a][i]==f[b][i]) continue; a=f[a][i],b=f[b][i]; } return f[a][0]; } void print(int x){ int num[N]; memset(num,0,sizeof(num)); if(!x) {puts("0");return;} if(x<0) {putchar('-');x=0-x;} while(x) num[++num[0]]=(x&1),x>>=1; for(int i=num[0];i>0;--i) printf("%d",num[i]); printf("\n"); } int main(){ //freopen("in.txt","r",stdin); rd(n),rd(m); for(int i=1,u,v;i<=m;++i) rd(u),rd(v),add(u,v),add(v,u); for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i,0); for(int i=1;i<=m;++i) if(bl[e[i<<1].u]!=bl[e[i<<1].v]) add2(bl[e[i<<1].u],bl[e[i<<1].v]),add2(bl[e[i<<1].v],bl[e[i<<1].u]); rd(q); dfs(1,0); for(int i=1,x,y,lca;i<=q;++i){ rd(x),rd(y),lca=LCA(bl[x],bl[y]); print(dep[bl[x]]+dep[bl[y]]-dep[lca]*2+1); } return 0; }