zoukankan      html  css  js  c++  java
  • BSOJ5458 [NOI2018模拟5]三角剖分Bsh 分治最短路

    题意简述

    给定一个正(n)边形及其三角剖分,每条边的长度为(1),给你(q)组询问,每次询问给定两个点(x_i)(y_i)的最短距离。

    做法

    显然正多边形的三角剖分是一个平面图,每一条剖分的边可以将正多边形分成有一条重边的两个独立的新多边形,显然这一个过程是可以用分治来实现的。

    我们对于分治过程中的多边形进行重新编号,找到两端点数最平均的边割去,对于点集(V),边集(E)和询问集(Q)分别开三个vector传入函数中。

    如果点集的大小等于了(3),我们就可以对单个三角形进行直接计算,否则对于集合进行左右的分治,贡献大小使用两次bfs计算,时间复杂度(O(n log{n}))

    代码实现

    #include<bits/stdc++.h>
    using namespace std;
    #define re register int
    #define in inline
    #define ll long long
    #define ak *
    #define db double
    in char getch()
    {
    	static char buf[1<<12],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<12,stdin),p1==p2)?EOF:*p1++;
    }
    char qwq;
    #define gc() getch()
    in int read()
    {
    	re cz=0,ioi=1;qwq=gc();
    	while(qwq<'0'||qwq>'9') ioi=qwq=='-'?~ioi+1:1,qwq=gc();
    	while(qwq>='0'&&qwq<='9') cz=(cz<<3)+(cz<<1)+(qwq^48),qwq=gc();
    	return cz ak ioi;
    }
    #define vec vector
    #define pb push_back
    const int N=6e4+5;
    int n,m,h[N],cnt,dx[N],dy[N],ans[N<<1],siz[N],le[N],ri[N],vis[N];
    struct did{int next,to;}e[N<<2];
    struct edge{int u,v;};
    struct que{int a,b,id;};
    vec<edge>ed;
    vec<que>qr;
    vec<int>ve;
    in void Add(re x,re y) {e[++cnt]=(did){h[x],y},h[x]=cnt;}
    in void add(re x,re y) {Add(x,y);Add(y,x);}
    queue<int>q;
    in void bfs(re s,re *dis)
    {
    	dis[s]=0;q.push(s);
    	while(!q.empty())
    	{
    		re u=q.front();q.pop();
    		for(re i=h[u],v;v=e[i].to,i;i=e[i].next)
    		if(dis[v]>=1e9&&vis[v]) dis[v]=dis[u]+1,q.push(v);
    	}	
    }
    void divide(vec<int>v,vec<edge>ed,vec<que>qr)
    {
    	if(!qr.size()) return;
    	if(v.size()==3)
    	{
    		for(re i=0;i<qr.size();i++)
    		ans[qr[i].id]=((qr[i].a==qr[i].b)^1);
    		return;
    	}
    	vec<int>v1,v2;v1.clear(),v2.clear();
    	vec<edge>e1,e2;e1.clear(),e2.clear();
    	vec<que>q1,q2;q1.clear(),q2.clear();
    	re n=v.size(),m=ed.size();
        for(re i=0;i<n;i++) siz[v[i]]=0;siz[v[0]]=1;
        for(re i=1;i<n;i++) siz[v[i]]=siz[v[i-1]]+1;
        re x=0,y=0,minn=1e9;
        for(re i=0;i<m;i++) 
    	{
            re u=ed[i].u,v=ed[i].v,len=siz[v]-siz[u]-1;
            if(max(len,n-2-len)<minn) 
    		minn=max(len,n-2-len),x=u,y=v;
    	}
    	for(re i=0;i<n;i++)
    	{
    		if(v[i]>=x&&v[i]<=y) le[v[i]]=1,v1.pb(v[i]);
    		if(v[i]<=x||v[i]>=y) ri[v[i]]=1,v2.pb(v[i]);
    	}
    	for(re i=0;i<m;i++)
    	{
    		re u=ed[i].u,v=ed[i].v;
    		if(le[u]&&le[v]) e1.pb(ed[i]);
    		if(ri[u]&&ri[v]) e2.pb(ed[i]);
    	}
    	for(re i=0;i<qr.size();i++)
    	{
    		re a=qr[i].a,b=qr[i].b;
    		if(le[a]&&le[b]) q1.pb(qr[i]);
    		if(ri[a]&&ri[b]) q2.pb(qr[i]);
    	}	
    	for(re i=0;i<n;i++) vis[v[i]]=1,dx[v[i]]=dy[v[i]]=1e9;
    	bfs(x,dx);bfs(y,dy);
    	for(re i=0;i<qr.size();i++)
    	{
    		re a=qr[i].a,b=qr[i].b,id=qr[i].id;
    		re lenx=dx[a]+dx[b],leny=dy[a]+dy[b];
    		ans[id]=min(min(ans[id],min(lenx,leny)),min(dx[a]+dy[b],dx[b]+dy[a])+1);
    	}
    	for(re i=0;i<n;i++) vis[v[i]]=le[v[i]]=ri[v[i]]=0;
    	divide(v1,e1,q1);divide(v2,e2,q2);
    }	
    int main()
    {
    	freopen("bsh.in","r",stdin);
    	freopen("bsh.out","w",stdout);
    	n=read();
    	for(re i=1;i<=n;i++) add(i,i+1-n*(i==n));
    	for(re i=1;i<=n-3;i++)
    	{
    		re x=read(),y=read();
    		add(x,y);if(x>y) swap(x,y);
    		ed.pb((edge){x,y});
    	}
    	for(re i=1;i<=n;i++) ve.pb(i);
    	m=read();
    	for(re i=1;i<=m;i++) 
    	{
    		re x=read(),y=read();
    		if(x>y) swap(x,y);
    		qr.pb((que){x,y,i});
    	}
    	memset(ans,127,sizeof(ans));
    	divide(ve,ed,qr);
    	for(re i=1;i<=m;i++) printf("%d
    ",ans[i]);
    }
    
  • 相关阅读:
    JavaScript——实现compose函数
    Typora——如何画流程图 | mermaid-js
    Electron——复制文件操作
    JavaScript——实现一些常用函数
    vue elementUI表单主动trigger某个rules校验
    [java]多线程——多线程debug调试(非常非常详细的调试)
    CompletableFuture supplyAsync() and thenApply() 用法区别
    CAS和MySql乐观锁实现下单
    TiDB集群手动安装
    Vue中 let _this = this的作用
  • 原文地址:https://www.cnblogs.com/disangan233/p/11170823.html
Copyright © 2011-2022 走看看