因为是三角剖分,所以每一条对角线都把多边形分成两部分,于是考虑分治。
先找到一条把多边形分得比较均匀的对角线,对两个端点做一下bfs,处理掉起点和终点分别在这条对角线两侧的询问(分经过某个点或者经过这条边三种情况更新),然后继续分治直到三角形为止。
选对角线的时候直接选最远的即可。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 52010
#define fs first
#define sc second
#define chkmin(a,b) a=min(a,b)
#define in(x) (x>dx&&x<dy)
#define out(x) (x<dx||x>dy)
using namespace std;
const int inf=0x3f3f3f3f;
int n,m,a[N],b[N],d1[N],d2[N],vis[N],dl[N];
int read()
{
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=-1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
return x*f;
}
struct edge
{
int t;bool b;
edge *next;
}*con[N];
struct node
{
int x,y,id,ans;
}q[N<<1],s[N<<1];
bool cmp(node p,node q)
{
return p.id<q.id;
}
void ins(int x,int y,bool b)
{
edge *p=new edge;
p->t=y;p->b=b;
p->next=con[x];
con[x]=p;
}
void bfs(int S,int l,int r,int *d)
{
for(int i=l;i<=r;i++)
d[a[i]]=inf;
d[S]=0;dl[1]=S;
for(int hd=1,tl=1,v=S;hd<=tl;v=dl[++hd])
for(edge *p=con[v];p;p=p->next)
if(vis[p->t]&&d[p->t]==inf)
d[p->t]=d[v]+1,dl[++tl]=p->t;
}
void solve(int l,int r,int L,int R)
{
if(l>r||L>R) return ;
for(int i=l;i<=r;i++)
vis[a[i]]=i-l+1;
int o=r-l+1;
if(o<=3)
{
for(int i=l;i<=r;i++)
{
bfs(a[i],l,r,d1);
for(int j=L;j<=R;j++)
if(q[j].x==a[i]) chkmin(q[j].ans,d1[q[j].y]);
}
return ;
}
int dx,dy,d=0;
for(int i=l;i<=r;i++)
for(edge *p=con[a[i]];p;p=p->next)
if(p->b&&vis[p->t]>vis[a[i]])
{
int tmp=min(vis[p->t]-vis[a[i]],o-vis[p->t]+vis[a[i]]);
if(tmp>d) d=tmp,dx=a[i],dy=p->t;
}
if(d==0)return ;
bfs(dx,l,r,d1);bfs(dy,l,r,d2);
for(int i=L;i<=R;i++)
chkmin(q[i].ans,min(min(d1[q[i].x]+d2[q[i].y],d1[q[i].y]+d2[q[i].x])+1,min(d1[q[i].x]+d1[q[i].y],d2[q[i].y]+d2[q[i].x])));
int Top=L-1,mT,nT,top=l-1,mt,nt;
for(int i=L;i<=R;i++)
if(in(q[i].x)&&in(q[i].y)) s[++Top]=q[i];
mT=Top;
for(int i=L;i<=R;i++)
if(out(q[i].x)&&out(q[i].y)) s[++Top]=q[i];
nT=Top;
for(int i=L;i<=R;i++)
if(!(in(q[i].x)&&in(q[i].y))&&!(out(q[i].x)&&out(q[i].y))) s[++Top]=q[i];
for(int i=L;i<=R;i++)
q[i]=s[i];
for(int i=l;i<=r;i++)
if(in(a[i])&&in(a[i])) b[++top]=a[i];
mt=top;
for(int i=l;i<=r;i++)
if(out(a[i])&&out(a[i])) b[++top]=a[i];
nt=top;
for(int i=l;i<=r;i++)
if(!(in(a[i])&&in(a[i]))&&!(out(a[i])&&out(a[i]))) b[++top]=a[i];
for(int i=l;i<=r;i++)
a[i]=b[i];
for(int i=l;i<=r;i++)
vis[a[i]]=0;
solve(l,mt,L,mT);
solve(mt+1,nt,mT+1,nT);
}
int main()
{
n=read();
for(int i=1;i<n;i++)
ins(i,i+1,0),ins(i+1,i,0);
ins(1,n,0);ins(n,1,0);
for(int i=1;i<=n-3;i++)
{
int x=read(),y=read();
ins(x,y,1);ins(y,x,1);
}
m=read();
for(int i=1;i<=m;i++)
{
q[i].x=read();q[i].y=read();
q[i].id=i;
if(q[i].x>q[i].y) swap(q[i].x,q[i].y);
q[i].ans=min(q[i].y-q[i].x,n-q[i].y+q[i].x);
}
for(int i=1;i<=n;i++)
a[i]=i;
solve(1,n,1,m);
sort(q+1,q+m+1,cmp);
for(int i=1;i<=m;i++)
printf("%d\n",q[i].ans);
return 0;
}