题解

直接分治啊啊啊啊啊啊啊啊!!!!!!!!!!

找一条对角线,把两边的点数尽量分的均匀

然后在这个图中用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]);
}