【NOI2018模擬5】三角剖分Bsh

【NOI2018模擬5】三角剖分Bsh

Description

  給定一個正 n 邊形及其三角剖分,共 2n - 3 條邊 (n條多邊形的邊和n-3 條對角線),每條邊的長度爲 1。   共 q 次詢問,每次詢問給定兩個點,求它們的最短距離。c++

Input

  第一行一個整數 n ,表示多邊形的點數;   接下來 n - 3 行,每行兩個整數 ui,vi,表示一條 ai 和 bi 之間的對角線;   接下來一行一個整數 q,表示詢問個數;   接下來 q 行,每行兩個整數 xi,yi,表示第 i 次詢問的起點和終點;ui

Output

  對於每個詢問輸出一個整數,表示答案。spa

Sample Input

6 1 5 2 4 5 2 5 1 3 2 5 3 4 6 3 6 6code

Sample Output

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;
}
相關文章
相關標籤/搜索