原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3911

直接求最小生成树显然边太多,考虑少用点边。

连出来的边肯定是没相交的,我们需要做一下三角剖分,求出可能的待选边。

这个很资瓷:http://www.geom.uiuc.edu/~samuelp/del_project.html

三角剖分大约就是分治到3个点以内直接两两连边,合并两个块的时候需要先求出下凸包,找到最底下的一条边先连起来,然后找这条边与其他未处理的点能构成的最小圆(没有其他点在这个圆内)。删掉相交的边然后不断把底边往上抬(这里需要结合图来理解)。

最后有一些细节诸如求凸包的时候三点共线要保留什么的。一开始还在纠结删边的时候点在边上怎么处理,后来才发现并不会有这种情况。

#include<cmath>
#include<cstdio>
#include<algorithm>
#define eps 1e-12
#define MN 100001
#define ll long long
#define ld double
using namespace std; int read_p,read_ca;
inline int read(){
read_p=;read_ca=getchar();
while(read_ca<''||read_ca>'') read_ca=getchar();
while(read_ca>=''&&read_ca<='') read_p=read_p*+read_ca-,read_ca=getchar();
return read_p;
}
struct po{int x,y;};
struct na{po p;int n;}p[MN];
struct e{int x,y,ne,pre;}b[MN<<];
struct _e{int y,ne;ll z;}_b[MN];
struct bi{int x,y;ll z;}B[MN<<];
bool operator < (bi a,bi b){return a.z<b.z;}
bool operator < (na a,na b){return a.p.x==b.p.x?a.p.y<b.p.y:a.p.x<b.p.x;}
int n,m,num=,l[MN],st[MN],top,ct[MN],NUM=,x,y,_l[MN],_num=,fa[MN],f[MN][],de[MN];
ll v[MN][];
inline void in(int x,int y,ll z){_b[++_num].y=y;_b[_num].z=z;_b[_num].ne=_l[x];_l[x]=_num;}
inline void _add(int x,int y){b[++num].x=x;b[num].y=y;b[num].ne=l[x];b[l[x]].pre=num;l[x]=num;}
inline void add(int x,int y){_add(x,y);_add(y,x);}
inline void _del(int i){if(l[b[i].x]==i)l[b[i].x]=b[i].ne;else{b[b[i].pre].ne=b[i].ne;if(b[i].ne)b[b[i].ne].pre=b[i].pre;}}
inline void del(int i){_del(i);_del(i^);}
inline int max(int a,int b){return a>b?a:b;}
ll cha(po a,po b,po c){return 1LL*(b.x-a.x)*(c.y-b.y)-1LL*(c.x-b.x)*(b.y-a.y);}
bool _cha(po a,po b,po c){return cha(a,b,c)<=;}
inline bool ju(po a,po b,po c,po d){return (_cha(a,b,c)^_cha(a,b,d))&&(_cha(c,d,a)^_cha(c,d,b));}
ll sqr(int &x){return 1LL*x*x;}
ld sqr(ld x){return x*x;}
bool incir(po a,po b,po c,po d){
ll m=(1LL*a.x*(b.y-c.y)+1LL*b.x*(c.y-a.y)+1LL*c.x*(a.y-b.y))<<;
ld x=(ld)(sqr(a.x)*(b.y-c.y)+sqr(b.x)*(c.y-a.y)+sqr(c.x)*(a.y-b.y)-1LL*(a.y-b.y)*(b.y-c.y)*(c.y-a.y))/m;
ld y=(ld)(1LL*(a.x-b.x)*(b.x-c.x)*(c.x-a.x)-sqr(a.y)*(b.x-c.x)-sqr(b.y)*(c.x-a.x)-sqr(c.y)*(a.x-b.x))/m;
return sqrt(sqr(x-a.x)+sqr(y-a.y))+eps>sqrt(sqr(x-d.x)+sqr(y-d.y));
}
void work(int L,int R){
if (R-L<=){
for (int i=L;i<=R;i++) ct[p[i].n]=i;
for (int i=L;i<R;i++)
for (int j=i+;j<=R;j++) add(i,j);
return;
}
int mid=L+R>>;
work(L,mid);work(mid+,R);
top=;
for (int i=L;i<=R;st[++top]=i++)
while (top>&&cha(p[st[top-]].p,p[st[top]].p,p[i].p)<) top--;
int Ld,Rd,id;
for (int i=;i<top;i++)
if (st[i]<=mid&&st[i+]>mid) Ld=st[i],Rd=st[i+];
add(Ld,Rd);
for(;;){
id=-;
for (int i=l[Ld];i;i=b[i].ne)
if (b[i].y!=Rd)
if (cha(p[b[i].y].p,p[Ld].p,p[Rd].p)>&&(id==-||incir(p[Ld].p,p[Rd].p,p[id].p,p[b[i].y].p))) id=b[i].y;
for (int i=l[Rd];i;i=b[i].ne)
if (b[i].y!=Ld)
if (cha(p[Ld].p,p[Rd].p,p[b[i].y].p)>&&(id==-||incir(p[Ld].p,p[Rd].p,p[id].p,p[b[i].y].p))) id=b[i].y;
if (id==-) break; if (id<=mid){
for (int i=l[Ld];i;i=b[i].ne)
if (b[i].y!=Rd)
if (ju(p[id].p,p[Rd].p,p[b[i].y].p,p[Ld].p)) del(i);
Ld=id;
}else{
for (int i=l[Rd];i;i=b[i].ne)
if (b[i].y!=Ld)
if (ju(p[id].p,p[Ld].p,p[b[i].y].p,p[Rd].p)) del(i);
Rd=id;
}
add(Ld,Rd);
}
}
int gf(int x){return fa[x]==x?x:fa[x]=gf(fa[x]);}
void dfs(int x,int _f){
for (int i=;i<;i++) f[x][i]=f[f[x][i-]][i-],v[x][i]=max(v[x][i-],v[f[x][i-]][i-]);
for (int i=_l[x];i;i=_b[i].ne)
if (_b[i].y!=_f) de[_b[i].y]=de[x]+,f[_b[i].y][]=x,v[_b[i].y][]=_b[i].z,dfs(_b[i].y,x);
}
ll Mavis(int x,int y){
ll mmh=;
if (de[x]<de[y]) swap(x,y);
for (int i=;i>=;i--)
if (de[y]<=de[f[x][i]]){
if (v[x][i]>mmh) mmh=v[x][i];
x=f[x][i];
}
if (x==y) return mmh;
for (int i=;i>=;i--)
if (f[y][i]!=f[x][i]){
if (v[x][i]>mmh) mmh=v[x][i];
if (v[y][i]>mmh) mmh=v[y][i];
x=f[x][i];y=f[y][i];
}
if (v[x][]>mmh) mmh=v[x][];
if (v[y][]>mmh) mmh=v[y][];
return mmh;
}
int main(){
register int i,j;
n=read();
for (i=;i<n;i++) p[i].p.x=read(),p[i].p.y=read(),p[i].n=i+,fa[i]=i;
sort(p,p+n);
work(,n-);
for (i=;i<n;i++)
for (j=l[i];j;j=b[j].ne) if (b[j].y>i) B[NUM].x=i,B[NUM].y=b[j].y,B[NUM++].z=sqr(p[i].p.x-p[b[j].y].p.x)+sqr(p[i].p.y-p[b[j].y].p.y);
sort(B,B+NUM);
for (i=;i<NUM;i++){
if (p[B[i].x].n>p[B[i].y].n) swap(B[i].x,B[i].y);
int x=gf(B[i].x),y=gf(B[i].y);
if (x==y) continue;
fa[x]=y;
in(B[i].x,B[i].y,B[i].z);in(B[i].y,B[i].x,B[i].z);
}
dfs(,);
m=read();
while (m--){
x=ct[read()];y=ct[read()];
printf("%.6lf\n",sqrt(Mavis(x,y)));
}
}

upd 2017/12/26

  代码被hack了,当初应该是对着n+e的blog学的吧,所以他n^2我也n^2了……

  最近已经无力捣鼓优化惹,直接贴一下别人blog吧:https://www.cnblogs.com/darklove/p/8056097.html

BZOJ:3911: SGU383 Caravans(三角剖分)的更多相关文章

  1. bzoj AC倒序

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

  2. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  3. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  4. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  5. bzoj 4610 Ceiling Functi

    bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...

  6. BZOJ 题目整理

    bzoj 500题纪念 总结一发题目吧,挑几道题整理一下,(方便拖板子) 1039:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...

  7. 【sdoi2013】森林 BZOJ 3123

    Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负整数 ...

  8. 【清华集训】楼房重建 BZOJ 2957

    Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些 ...

  9. 【splay】文艺平衡树 BZOJ 3223

    Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3  ...

随机推荐

  1. 智能合约语言 Solidity 教程系列6 - 结构体与映射

    写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解, 如果你还不了解,建议你先看以太坊是什么 本系列文章一部分是参考Solidity官方文档(当前最新版 ...

  2. MongoDB集群搭建-副本集

    MongoDB集群搭建-副本集 概念性的知识,可以参考本人博客地址: 一.Master-Slave方案: 主从: 二.Replica Set方案: 副本集: 步骤:(只要按步骤操作,100%成功) 1 ...

  3. Java 本地开发环境搭建(框架采用 Spring+Spring MVC+Hibernate+Jsp+Gradle+tomcat+mysql5.6)

    项目搭建采用技术栈为:Spring+Spring MVC+Hibernate+Jsp+Gradle+tomcat+mysql5.6 搭建环境文档目录结构说明: 使用Intellj Idea 搭建项目过 ...

  4. 设计模式之 - 模板模式(Template Pattern)

    引入:这几天在看一本讲spring源码的书<SPRING技术内幕>里面在讲加载配置文件的时候,可以有不同的加载方式,如根据文件系统目录加载配置文件(FileSystemXmlApplica ...

  5. RabbitMQ教程(一) ——win7下安装RabbitMQ

    RabbitMQ依赖erlang,所以先安装erlang,然后再安装RabbitMQ; 下载RabbitMQ,下载地址: rabbitmq-server-3.5.6.exe和erlang,下载地址:o ...

  6. java 学习(二)

    public class Scoure { public static void main(String args[]) { int score=90; if (score>=85 && ...

  7. mintUI配合vue2.0,webpack,vue-cli脚手架从零搭建

    步骤说明: 1.确保安装了vue-cli 安装:cnpm install vue-cli -g 验证版本:vue --version 2.生成项目模板: vue init webpack-simple ...

  8. 三:Redis连接池、JedisPool详解、Redisi分布式

    单机模式: package com.ljq.utils; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; ...

  9. Node.js 蚕食计划(四)—— Express + SQL Server 搭建电影网站

    前段时间在慕课网上看了 scott 大神的<node+mongodb建站攻略>课程,按照自己的思路做了一遍,发博客记录一下 一.项目介绍 这个项目是一个简单的电影网站,由首页.详情页.评论 ...

  10. Linux 定时任务不生效的问题

    Linux 中定时任务不生效的问题屡见不鲜, 本质原因是: 登录式 shell & 非登录式 shell. 登录式 shell & 非登录式 shell 登录式 shell 有: su ...