首先拓扑,每次取出度数为$2$的点,这样可以把所有三角形都找到。

那么建出对偶图,会发现是一棵树。

对这棵树进行点分治,每次取出重心,DFS求出所有在里面的点,然后从重心$3$个点分别做一次BFS。

对于每个询问,如果不经过重心这个区域,那么递归求解,否则用BFS的结果回答即可。

时间复杂度$O(n\log n)$。

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=50010,M=100010,U=M*20;
int n,m,i,x,y,z,d[N],g[N],v[N<<2],nxt[N<<2],ed,vis[N],h,t,q[N],ans[M];
struct Q{int x,y;}que[M];
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline void add(int x,int y){d[x]++;v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
namespace Graph{
int n,m,i,id[N][3],g[N],v[N<<1],nxt[N<<1],ok[N<<1],ed;
int all,f[N],son[N],now,pos[N],last[N],cur,dis[3][N];
int G[N],V[U],NXT[U],ED,p[N*3],cnt;
struct E{int x,y,p;E(){}E(int _x,int _y,int _p){x=_x,y=_y,p=_p;}}e[N*3];
inline bool cmp(const E&a,const E&b){return a.x==b.x?a.y<b.y:a.x<b.x;}
inline void add(int x,int y){
v[++ed]=y;ok[ed]=1;nxt[ed]=g[x];g[x]=ed;
v[++ed]=x;ok[ed]=1;nxt[ed]=g[y];g[y]=ed;
}
inline void ADD(int x,int y){V[++ED]=y;NXT[ED]=G[x];G[x]=ED;}
inline void newedge(int x,int y,int z){
n++;
id[n][0]=x,id[n][1]=y,id[n][2]=z;
e[++m]=E(min(x,y),max(x,y),n);
e[++m]=E(min(x,z),max(x,z),n);
e[++m]=E(min(y,z),max(y,z),n);
}
void findroot(int x,int y){
son[x]=1;f[x]=0;
for(int i=g[x];i;i=nxt[i])if(ok[i]&&v[i]!=y){
findroot(v[i],x);
son[x]+=son[v[i]];
if(son[v[i]]>f[x])f[x]=son[v[i]];
}
if(all-son[x]>f[x])f[x]=all-son[x];
if(f[x]<f[now])now=x;
}
void dfs(int x,int y,int z){
for(int i=0;i<3;i++){
pos[id[x][i]]=z;
last[id[x][i]]=cur;
p[++cnt]=id[x][i];
}
for(int i=g[x];i;i=nxt[i])if(ok[i]&&v[i]!=y)dfs(v[i],x,z);
}
inline void bfs(int S,int*d){
int i,x,y,h,t;static int q[N];
for(i=1;i<=cnt;i++)d[p[i]]=U;
d[q[h=t=1]=S]=0;
while(h<=t)for(i=::g[x=q[h++]];i;i=::nxt[i]){
y=::v[i];
if(d[y]<U||last[y]<cur)continue;
d[q[++t]=y]=d[x]+1;
}
}
void solve(int x){
if(!G[x])return;
f[0]=all=son[x],findroot(x,now=0);
int i,j,A,B;
cur++;
for(cnt=0,i=g[now];i;i=nxt[i])if(ok[i])dfs(v[i],now,v[i]);
for(i=0;i<3;i++){
p[++cnt]=A=id[now][i];
pos[A]=now,last[A]=cur;
}
for(i=0;i<3;i++)bfs(id[now][i],dis[i]);
for(cnt=0,i=G[x];i;i=NXT[i])p[++cnt]=V[i];G[x]=0;
for(i=1;i<=cnt;i++){
A=que[p[i]].x,B=que[p[i]].y;
if(pos[A]==pos[B])
if(pos[A]==now)ans[p[i]]=1;
else ADD(pos[A],p[i]);
else for(j=0;j<3;j++)ans[p[i]]=min(ans[p[i]],dis[j][A]+dis[j][B]);
}
for(i=g[now];i;i=nxt[i])if(ok[i])ok[i^1]=0,solve(v[i]);
}
void Main(){
sort(e+1,e+m+1,cmp);
for(ed=i=1;i<m;i++)if(e[i].x==e[i+1].x&&e[i].y==e[i+1].y)add(e[i].p,e[i+1].p);
son[1]=n;solve(1);
}
}
int main(){
read(n);
for(i=1;i<n;i++)add(i,i+1),add(i+1,i);
add(1,n),add(n,1);
for(i=1;i<=n-3;i++)read(x),read(y),add(x,y),add(y,x);
for(h=i=1;i<=n;i++)if(d[i]==2)q[++t]=i;
while(h<=t){
x=q[h++];
if(d[x]!=2)continue;
vis[x]=1,y=0;
for(i=g[x];i;i=nxt[i])if(!vis[v[i]]){
if(y)z=v[i];else y=v[i];
if((--d[v[i]])==2)q[++t]=v[i];
}
Graph::newedge(x,y,z);
}
read(m);
for(i=1;i<=m;i++){
read(x),read(y);
if(x!=y)que[i].x=x,que[i].y=y,Graph::ADD(1,i),ans[i]=U;
}
Graph::Main();
for(i=1;i<=m;i++)printf("%d\n",ans[i]);
return 0;
}

  

BZOJ4449 : [Neerc2015]Distance on Triangulation的更多相关文章

  1. 【bzoj 4449】[Neerc2015]Distance on Triangulation

    Description 给定一个凸n边形,以及它的三角剖分.再给定q个询问,每个询问是一对凸多边行上的顶点(a,b),问点a最少经过多少条边(可以是多边形上的边,也可以是剖分上的边)可以到达点b. I ...

  2. bzoj 4449: [Neerc2015]Distance on Triangulation

    Description 给定一个凸n边形,以及它的三角剖分.再给定q个询问,每个询问是一对凸多边行上的顶点(a,b),问点a最少经过多少条边(可以是多边形上的边,也可以是剖分上的边)可以到达点b. I ...

  3. 【BZOJ 4449】[Neerc2015]Distance on Triangulation 多边形分治结构

    这题好神啊……正解方向是分治,据我所知的分治方法有:I.离线后直接对多边形以及所有的询问进行分治 II.建立多边形的分治结构(对于三角形来说类似线段树,对于对角线来说类似平衡树),然后每次在这个分治结 ...

  4. Gym 100851 Distance on Triangulation

    题意:给你一个N边形, 然后这个n边形有n-3条边,然后询问2点之间的最短路. 题解:分治. 我们可以找到一条边,使得这幅图能分成大小相同的2幅图,那么我们就可以确定那些被分割开的询问的答案是多少了. ...

  5. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  6. NEERC15

    2015-2016 ACM-ICPC Northeastern European Regional Contest 再开一个新坑吧 目前姿势有限,C.H.I仍然处于弃坑状态 代码戳这里 Problem ...

  7. Signed Distance Field Shadow in Unity

    0x00 前言 最近读到了一个今年GDC上很棒的分享,是Sebastian Aaltonen带来的利用Ray-tracing实现一些有趣的效果的分享. 其中有一段他介绍到了对Signed Distan ...

  8. [LeetCode] Total Hamming Distance 全部汉明距离

    The Hamming distance between two integers is the number of positions at which the corresponding bits ...

  9. [LeetCode] Hamming Distance 汉明距离

    The Hamming distance between two integers is the number of positions at which the corresponding bits ...

随机推荐

  1. Linq to json

    Json.Net系列教程 4.Linq To JSON 一.Linq to JSON是用来干什么的? Linq to JSON是用来操作JSON对象的.可以用于快速查询,修改和创建JSON对象.当JS ...

  2. SQLServer系统监控

    http://blog.sina.com.cn/s/blog_519d269c0100gx09.html http://blog.csdn.net/qxlwuyuhui0801/article/det ...

  3. Delphi测试线程的时间

    在16位时代,当我们在Windows3.x下编程时,经常会用到GetTickCount()或者timeGetTime()来判断一段代码的执行时间.示例如下 var StartTime, Total: ...

  4. 【JAVA集合框架之Set】

    一.Set概述. Set集合的特点是元素不允许重复,而且是无序的(添加和取出的顺序不一致). Set接口中的方法和Collection接口中的方法几乎相同,略. Set接口下常用的两个类:HashSe ...

  5. 2016"百度之星" - 初赛(Astar Round2A)All X(数学 矩阵)

    All X  Accepts: 1281  Submissions: 7580  Time Limit: 2000/1000 MS (Java/Others)  Memory Limit: 65536 ...

  6. Grafana 安装

    由于 Grafana 是存静态的,你只需要下载源代码解压,将它部署在 Nginx 上面就可以了,或者可以用 Python 的 SimpleHTTPServer 来跑 $ wget http://gra ...

  7. phpMailer邮件发送

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. 连接SQL Server执行SQL语句

    public static DataTable GetData() { string Connect = ConfigurationManager.AppSettings["Connecti ...

  9. ubuntu wubi非在线快速安装

    最近ubuntu更新了,就想把它重新装回来试一下,但是由于种种原因划分磁盘不太方便,很自然就想到了wubi,这个不仅仅安全性高,而且比直接装系统快多了,而且方便.但是在线安装实在是太慢了,所以就找到了 ...

  10. 1080P、720P、4CIF、CIF所需要的理论带宽

    转自:http://blog.sina.com.cn/s/blog_64684bf30101hdl7.html 在视频监控系统中,对存储空间容量的大小需求是与画面质量的高低.及视频线路等都有很大关系. ...