emmm…这算是一道模板题吧,但当初没多少人过了,然后就决定来写篇题解,毕竟也好久没写了。。。
(本题来自HLOJ#1578)
呃,题目就是给你一张图,然后求a节点到b节点必须经过几条边。
这题呢可能会出现两个点有两条不同的路径,显然这两点组成了一个环。那么我们思考环的特性。
显然环是没有割边与割点的。由此想到Tarjan算法求联通分量。
这样就进行了缩点,使得题中的图变成了一棵树。
而一定经过的边即是割边,所以再求割边数即可。
于是就建图+缩点+lca+两个dfs,结束。。。
感觉好快。。。
再贴个代码帮助理解(表示懒得去掉宏定义,所以。。。见谅)
#include
using namespace std;
#define s1(a,n) sort(a+1,a+n+1)
#define s2(a,n) sort(a+1,a+n+1,mc)
#define ll long long
#define sg string
#define st struct
#define db double
#define f1(i,l,r) for(int i=l;i<=r;++i)
#define f2(i,r,l) for(int i=r;i>=l;--i)
#define f3(i,a,b) for(int i=a;i;i=b)
#define me(a,b) memset(a,b,sizeof(a))
#define sf scanf
#define pf printf
#define fi(a) freopen(a,"r",stdin)
#define fo(a) freopen(a,"w",stdout)
#define cn continue
#define bk break
#define rt return
#define ct const
ct int maxn=100000+10;
ct int maxm=200000+10;
int l,r,n,m,q,k,s=0,s1=0,t=0,num=0,ans=0,d[maxn],f[maxn][25],dfn[maxn],low[maxn],c[maxm],c1[maxn],vis[maxn],Top[maxn];
st lol{
int x,y,z;
}e[maxm*2];
st dota{
int a,b;
}e1[maxn*2];
bool mc(int x,int y){
rt x>y;
}
void ein(int u,int v,int w){
++ans;
e[ans].y=v;
e[ans].z=w;
e[ans].x=Top[u];
Top[u]=ans;
}
void init(){
sf("%d%d",&n,&m);
f1(i,1,m){
sf("%d%d",&e1[i].a,&e1[i].b);
ein(e1[i].a,e1[i].b,i);
ein(e1[i].b,e1[i].a,i);
}
}
void gg(int x,int y){
++num;
dfn[x]=low[x]=num;
f3(i,Top[x],e[i].x){
if(dfn[e[i].y]){
if(e[i].z!=y)
low[x]=min(low[x],dfn[e[i].y]);
cn;
}
gg(e[i].y,e[i].z);
low[x]=min(low[x],low[e[i].y]);
if(dfn[x]<low[e[i].y])
++c[e[i].z];
}
}
void hh(int x){
c1[x]=s;
f3(i,Top[x],e[i].x)
if(!c[e[i].z]&&!c1[e[i].y])
hh(e[i].y);
}
void kk(int x){
vis[x]=1;
f3(i,Top[x],e[i].x){
if(vis[e[i].y]) cn;
f[e[i].y][0]=x;
d[e[i].y]=d[x]+1;
kk(e[i].y);
}
}
int ee(int x,int y){
int ss=0,s2;
if(d[x]>d[y]) swap(x,y);
for(int i=0,t=d[y]-d[x];t;t>>=1,++i)
if(t&1)
y=f[y][i];
if(x==y) rt x;
s2=s;
while(s2){
++ss;
s2/=2;
}
f2(i,ss,0)
if(f[x][i]!=f[y][i]){
x=f[x][i];
y=f[y][i];
}
rt f[x][0];
}
void work(){
gg(1,0);
f1(i,1,n)
if(!c1[i]){
++s;
hh(i);
}
me(Top,0);
ans=0;
f1(i,1,m)
if(c1[e1[i].a]!=c1[e1[i].b]){
ein(c1[e1[i].a],c1[e1[i].b],i);
ein(c1[e1[i].b],c1[e1[i].a],i);
}
kk(1);
for(int i=1;i<<i<s;i++)
f1(j,1,s)
if(f[j][i-1])
f[j][i]=f[f[j][i-1]][i-1];
}
void prin(){
sf("%d",&q);
for(int i=1;i<=q;i++){
sf("%d%d",&l,&r);
k=ee(c1[l],c1[r]);
pf("%d\n",d[c1[l]]+d[c1[r]]-2*d[k]);
}
}
int main(){
fi("test.in");
fo("test.out");
init();
work();
prin();
rt 0;
}