給定一個正 n 邊形及其三角剖分,共 2n - 3 條邊 (n條多邊形的邊和n-3 條對角線),每條邊的長度爲 1。 共 q 次詢問,每次詢問給定兩個點,求它們的最短距離。c++
第一行一個整數 n ,表示多邊形的點數; 接下來 n - 3 行,每行兩個整數 ui,vi,表示一條 ai 和 bi 之間的對角線; 接下來一行一個整數 q,表示詢問個數; 接下來 q 行,每行兩個整數 xi,yi,表示第 i 次詢問的起點和終點;ui
對於每個詢問輸出一個整數,表示答案。spa
6 1 5 2 4 5 2 5 1 3 2 5 3 4 6 3 6 6code
2 1 1 3 0ip
$n\leq 52000,1\leq q\leq 2n$get
由於這是個平面圖,咱們發現,選取一條邊以後能夠將圖分爲兩個部分,兩個部分之間的最短路必定通過了這條邊的兩個端點中至少一個。it
又由於這是三角剖分,因此咱們能夠找到中間點使得左右兩邊的點數很是接近。因此咱們能夠分治。io
代碼:class
#include<bits/stdc++.h> #define ll long long #define N 150000 using namespace std; inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;} int n,m; struct road { int to,nxt; }s[N<<1]; int h[N],cnt; void add(int i,int j) {s[++cnt]=(road) {j,h[i]};h[i]=cnt;} #define pr pair<int,int> #define mp(a,b) make_pair(a,b) bool vis[N]; int dis1[N],dis2[N]; queue<int>q; void bfs(int S,int *dis) { q.push(S); dis[S]=0; while(!q.empty()) { int v=q.front(); q.pop(); for(int i=h[v];i;i=s[i].nxt) { int to=s[i].to; if(!vis[to]) continue ; if(dis[to]>1e9) { dis[to]=dis[v]+1; q.push(to); } } } } struct query {int x,y,id;}; int pre[N]; int ans[N]; int tag1[N],tag2[N]; int tim; void solve(vector<int>V,vector<pr>E,vector<query>Q) { if(!Q.size()) return ; if(V.size()==3) { for(int i=0;i<Q.size();i++) { int x=Q[i].x,y=Q[i].y; if(x==y) ans[Q[i].id]=0; else ans[Q[i].id]=1; } return ; } int n=V.size(),m=E.size(); int mid=(n-2)>>1; for(int i=0;i<n;i++) pre[V[i]]=0; pre[V[0]]=1; for(int i=1;i<n;i++) pre[V[i]]=pre[V[i-1]]+1; int id; int X=0,Y=0; int MN=1e9; for(int i=0;i<m;i++) { int x=E[i].first,y=E[i].second; int now=pre[y]-pre[x]-1; if(max(now,n-2-now)<MN) { MN=max(now,n-2-now); X=x,Y=y; } } vector<int>v1,v2; vector<pr>e1,e2; vector<query>q1,q2; v1.clear(),e1.clear(),q1.clear(); v2.clear(),e2.clear(),q2.clear(); for(int i=0;i<n;i++) { if(X<=V[i]&&V[i]<=Y) tag1[V[i]]=1; if(V[i]>=Y||V[i]<=X) tag2[V[i]]=1; } for(int i=0;i<n;i++) { if(tag1[V[i]]) v1.push_back(V[i]); if(tag2[V[i]]) v2.push_back(V[i]); } for(int i=0;i<m;i++) { int x=E[i].first,y=E[i].second; if(tag1[x]&&tag1[y]) e1.push_back(E[i]); if(tag2[x]&&tag2[y]) e2.push_back(E[i]); } for(int i=0;i<Q.size();i++) { if(tag1[Q[i].x]&&tag1[Q[i].y]) q1.push_back(Q[i]); if(tag2[Q[i].x]&&tag2[Q[i].y]) q2.push_back(Q[i]); } for(int i=0;i<n;i++) { dis1[V[i]]=dis2[V[i]]=1e9+7; vis[V[i]]=1; } bfs(X,dis1); bfs(Y,dis2); for(int i=0;i<Q.size();i++) { int x=Q[i].x,y=Q[i].y,id=Q[i].id; ans[id]=min(ans[id],dis1[x]+dis1[y]); ans[id]=min(ans[id],dis2[x]+dis2[y]); ans[id]=min(ans[id],dis1[x]+dis2[y]+1); ans[id]=min(ans[id],dis2[x]+dis1[y]+1); } for(int i=0;i<n;i++) tag1[V[i]]=tag2[V[i]]=vis[V[i]]=0; solve(v1,e1,q1),solve(v2,e2,q2); } vector<int>V; vector<pr>E; vector<query>Q; int main() { n=Get(); for(int i=1;i<n;i++) add(i,i+1),add(i+1,i); add(1,n),add(n,1); for(int i=1;i<=n-3;i++) { int x=Get(),y=Get(); add(x,y),add(y,x); if(x>y) swap(x,y); E.push_back(mp(x,y)); } memset(ans,0x3f,sizeof(ans)); for(int i=1;i<=n;i++) V.push_back(i); m=Get(); for(int i=1;i<=m;i++) { int x=Get(),y=Get(); if(x>y) swap(x,y); Q.push_back((query) {x,y,i}); } solve(V,E,Q); for(int i=1;i<=m;i++) cout<<ans[i]<<"\n"; return 0; }