题解
直接分治啊啊啊啊啊啊啊啊!!!!!!!!!!
找一条对角线,把两边的点数尽量分的均匀
然后在这个图中用bfs求出这条对角线两个端点到其它所有点的距离
一次是O(n)的(注意对角线是不会交叉的,所以在左右两个部分的点想要到达对方,就必定会经过中间的分割边的端点,如果走到分治的区域之外,它一定会浪费步数)
由于n的规模在分治中不断减小,分治层数是logn的,所以总时间复杂度是O(nlogn)的
代码;(有点难写)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define N 55005
int ans[2*N];
struct enode{
int u,v;
enode(){}
enode(int x,int y){u=x;v=y;}
};
struct qnode{
int u,v,id;
qnode(){}
qnode(int x,int y,int z){u=x;v=y;id=z;}
};
vector<int> G[N];
int dis[N],siz[N];
bool L[N],R[N];
void bfs(int s)
{
queue<int> q;
int u,v,i;
q.push(s);dis[s]=0;
while(!q.empty()){
u=q.front();q.pop();
for(i=0;i<int(G[u].size());i++){
v=G[u][i];
if(dis[v]==-1){
dis[v]=dis[u]+1;
q.push(v);
}
}
}
}
inline int ab(int x){return x<0?-x:x;}
void solve(vector<int> &a,vector<enode> &e,vector<qnode> &q)
{
int n=a.size(),m=e.size(),Q=q.size(),i,mi=0x3f3f3f3f,u,v,x,y,tmp;
if(!Q)return;
if(n==3){
for(i=0;i<Q;i++)
ans[q[i].id]=(q[i].u!=q[i].v);
return;
}
siz[a[0]]=1;
for(i=1;i<n;i++)siz[a[i]]=siz[a[i-1]]+1;
for(i=0;i<m;i++){
x=e[i].u;y=e[i].v;
if((tmp=max(n-ab(siz[x]-siz[y]),ab(siz[x]-siz[y])))<mi)
mi=tmp,u=x,v=y;
}
if(u>v)swap(u,v);
vector<int> a0,a1;vector<enode> e0,e1;vector<qnode> q0,q1;
a0.clear();a1.clear();e0.clear();e1.clear();q0.clear();q1.clear();
for(i=0;i<n;i++){L[a[i]]=R[a[i]]=0;G[a[i]].clear();}
for(i=0;i<n;i++){
if(u<=a[i]&&a[i]<=v)L[a[i]]=1,a0.push_back(a[i]);
if(a[i]<=u||a[i]>=v)R[a[i]]=1,a1.push_back(a[i]);
}
for(i=0;i<m;i++){
x=e[i].u;y=e[i].v;
G[x].push_back(y);G[y].push_back(x);
if(L[x]&&L[y])e0.push_back(e[i]);
if(R[x]&&R[y])e1.push_back(e[i]);
}
for(i=0;i<Q;i++){
x=q[i].u;y=q[i].v;
if(L[x]&&L[y])q0.push_back(q[i]);
if(R[x]&&R[y])q1.push_back(q[i]);
}
for(i=0;i<n;i++)dis[a[i]]=-1;bfs(u);
for(i=0;i<Q;i++)ans[q[i].id]=min(ans[q[i].id],dis[q[i].u]+dis[q[i].v]);
for(i=0;i<n;i++)dis[a[i]]=-1;bfs(v);
for(i=0;i<Q;i++)ans[q[i].id]=min(ans[q[i].id],dis[q[i].u]+dis[q[i].v]);
solve(a0,e0,q0);
solve(a1,e1,q1);
}
vector<int> a;
vector<enode> e;
vector<qnode> q;
int main()
{
freopen("drive.in","r",stdin);
freopen("drive.out","w",stdout);
memset(ans,0x3f,sizeof(ans));
int n,m,Q,u,v,i;
scanf("%d",&n);m=n-3;
for(i=1;i<=n;i++){
a.push_back(i);
e.push_back(enode(i,i%n+1));
}
for(i=1;i<=m;i++){
scanf("%d%d",&u,&v);
e.push_back(enode(u,v));
}
scanf("%d",&Q);
for(i=1;i<=Q;i++){
scanf("%d%d",&u,&v);
q.push_back(qnode(u,v,i));
}
solve(a,e,q);
for(i=1;i<=Q;i++)
printf("%d\n",ans[i]);
}