题目戳这里
一句话题意
一个无向图,先缩掉所有的环,再询问两点直接隔了多少个点(两端也算)。
Solution
似乎难度称不上黑题,思路也很明显
直接Tarjan缩点后求LCA,深度之差就是相隔的点数。
但注意特判LCA=x或y的情况。
本来早就可以A了,结果居然LCA打错,无语...
可能难就难在代码比较长,有点绕,但是想清楚还是蛮好打的。
也没什么好说的,直接看代码吧。
Coding
#include<bits/stdc++.h>
using namespace std;
const int N = 500005;
struct road
{
int to,next;
}e[N*10];
int head[N],cnt,be[N],to[N],num[N];
void add(int x,int y)
{
cnt++;
e[cnt].to=y;
e[cnt].next=head[x];
head[x]=cnt;
}
int sum,color[N],low[N],ins[N],tim[N],sta[N],top=1,col;
void Tarjan(int x,int last)
{
tim[x]=low[x]=++sum;
sta[top++]=x;
ins[x]=1;
for(int i=head[x];i!=0;i=e[i].next)
{
if(e[i].to!=last)
{
if(ins[e[i].to]==0)
{
Tarjan(e[i].to,x);
low[x]=min(low[x],low[e[i].to]);
}
else if(ins[e[i].to]==1)
low[x]=min(low[x],tim[e[i].to]);
}
}
if(tim[x]==low[x])
{
col++;
do
{
top--;
color[sta[top]]=col;
ins[sta[top]]=-1;
}while(sta[top]!=x);
}
return ;
}
int n,m,news[N],fa[N],LCA[N][20],dep[N];
road edge[N*10];
void Readd(int x,int y)
{
cnt++;
edge[cnt].to=y;
edge[cnt].next=head[x];
head[x]=cnt;
}
queue<int> q;
bool lemon[N];
void dfs(int x,int deep,int last)
{
dep[x]=deep; fa[x]=last;
for(int i=head[x];i;i=edge[i].next)
if(edge[i].to!=last&&dep[edge[i].to]==0) dfs(edge[i].to,deep+1,x);
}
int Lca(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
int popx=x,popy=y,last;
int p=0,qu=dep[x]-dep[y];
while(qu>0)
{
if(qu%2==1) x=LCA[x][p];
qu/=2;
p++;
}
if(x!=y)
{
for(int j=19;j>=0;j--)
if(LCA[x][j]!=LCA[y][j]) x=LCA[x][j],y=LCA[y][j];
last=LCA[x][0];
}
else last=y;
if(popy==last) return dep[popx]-dep[last]+1;
else return dep[popx]-dep[last]+dep[popy]-dep[last]+1;
}
void change(int num)
{
int ans[20],cl=0;
if(num==0) {cout<<0<<endl; return ;}
while(num>0)
{
ans[++cl]=num%2;
num/=2;
}
for(int i=cl;i>=1;i--)
printf("%d",ans[i]);
cout<<endl;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&be[i],&to[i]);
add(be[i],to[i]);
add(to[i],be[i]);
}
for(int i=1;i<=n;i++)
if(ins[i]==0) Tarjan(i,i);
for(int i=1;i<=n;i++)
num[color[i]]++;
memset(head,0,sizeof(head));
cnt=0;
for(int i=1;i<=m;i++)
if(color[be[i]]!=color[to[i]]||(color[be[i]]==color[to[i]]&&num[color[be[i]]]==2))
{
Readd(color[be[i]],color[to[i]]);
Readd(color[to[i]],color[be[i]]);
}
dfs(1,1,1);
for(int i=1;i<=col;i++)
LCA[i][0]=fa[i];
for(int j=1;j<=19;j++)
for(int i=1;i<=col;i++)
LCA[i][j]=LCA[LCA[i][j-1]][j-1];
int T;
cin>>T;
for(int i=1;i<=T;i++)
{
int x,y;
scanf("%d%d",&x,&y);
change(Lca(color[x],color[y]));
}
return 0;
}