BZOJ4449 : [Neerc2015]Distance on Triangulation
首先拓扑,每次取出度数为$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的更多相关文章
- 【bzoj 4449】[Neerc2015]Distance on Triangulation
Description 给定一个凸n边形,以及它的三角剖分.再给定q个询问,每个询问是一对凸多边行上的顶点(a,b),问点a最少经过多少条边(可以是多边形上的边,也可以是剖分上的边)可以到达点b. I ...
- bzoj 4449: [Neerc2015]Distance on Triangulation
Description 给定一个凸n边形,以及它的三角剖分.再给定q个询问,每个询问是一对凸多边行上的顶点(a,b),问点a最少经过多少条边(可以是多边形上的边,也可以是剖分上的边)可以到达点b. I ...
- 【BZOJ 4449】[Neerc2015]Distance on Triangulation 多边形分治结构
这题好神啊……正解方向是分治,据我所知的分治方法有:I.离线后直接对多边形以及所有的询问进行分治 II.建立多边形的分治结构(对于三角形来说类似线段树,对于对角线来说类似平衡树),然后每次在这个分治结 ...
- Gym 100851 Distance on Triangulation
题意:给你一个N边形, 然后这个n边形有n-3条边,然后询问2点之间的最短路. 题解:分治. 我们可以找到一条边,使得这幅图能分成大小相同的2幅图,那么我们就可以确定那些被分割开的询问的答案是多少了. ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- NEERC15
2015-2016 ACM-ICPC Northeastern European Regional Contest 再开一个新坑吧 目前姿势有限,C.H.I仍然处于弃坑状态 代码戳这里 Problem ...
- Signed Distance Field Shadow in Unity
0x00 前言 最近读到了一个今年GDC上很棒的分享,是Sebastian Aaltonen带来的利用Ray-tracing实现一些有趣的效果的分享. 其中有一段他介绍到了对Signed Distan ...
- [LeetCode] Total Hamming Distance 全部汉明距离
The Hamming distance between two integers is the number of positions at which the corresponding bits ...
- [LeetCode] Hamming Distance 汉明距离
The Hamming distance between two integers is the number of positions at which the corresponding bits ...
随机推荐
- C++中实现对象的clone()
在C#中,许多对象自动实现了clone函数,在C++中,要拷贝一个对象,除了自定义一个拷贝构造函数来实现对象复制外,还可以像C#中那样实现一个clone函数,这需要借助编译器实现的一个隐藏拷贝构造函数 ...
- 3.2 STL中的函数对象类模板
*: STL中有一些函数对象类模板,如下所示: 1)例如要求两个double类型的x 和y 的积,可以: multiplies<double>()(x,y); 该表达式的值就是x*y的值. ...
- Hadoop组件之-HDFS(HA实现细节)
NameNode 高可用整体架构概述 在 Hadoop 1.0 时代,Hadoop 的两大核心组件 HDFS NameNode 和 JobTracker 都存在着单点问题,这其中以 NameNode ...
- 20145206《Java程序设计》第10周学习总结
20145206 <Java程序设计>第10周学习总结 博客学习内容总结 什么是网络编程 网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据.程序员所作的事情就是把数据发送到指定 ...
- Mac系统下使用VirtualBox虚拟机安装win7--第二步 创建win7系统
第二步 创建win7系统 启动 Virtual Box 以后,点击窗口左上角的“新建”按钮,如图所示
- 与你相遇好幸运,CentOS 7 x86_64使用Yum安装PostgreSQL
访问http://yum.pgrpms.org/reporpms/repoview/letter_p.group.html,下载并安装和当前系统对应的rpm文件. wget https://downl ...
- Faster-rnnlm代码分析2 - HSTree的构造
也就是构造一棵Huffman Tree,输入是按照词汇频次由高到低排序的 采用层次SoftMax的做法,是为了使得训练和预测时候的softmax输出加速,原有multinomal softmax,是和 ...
- Asp.net窄屏页面 手机端新闻列表
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="SearchNotice.a ...
- Yii 同域名的单点登录 SSO实现
SSO (Single Sign-on) 顾名思义就是几个子项目共用一个登录点. 原理简单来说就是服务端session 共享, 客户端跨域cookies. 实现非常简单,protected/confi ...
- 闲谈SQL脚本优化
摘要: 闲来无事,便想寻找大师级别优化SQL脚本案例,也算是读后留点笔记,摘录内容都会链接到所参考网址,如有冒犯,还望博主见谅:有些文章只有多动手多动脑才能理解其中的意思,看了需要实际操作,才不枉大师 ...