1137: [POI2009]Wsp 岛屿

Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge
Submit: 165  Solved: 78
[Submit][Status][Discuss]

Description

Byteotia岛屿是一个凸多边形。城市全都在海岸上。按顺时针编号1到n。任意两个城市之间都有一条笔直的道路相连。道路相交处可以自由穿行。有一些道路被游击队控制了,不能走,但是可以经过这条道路与未被控制的道路的交点。问从城市1到n的最短距离。

Input

第一行正整数n m表示城市数和被控制的岛屿数(3≤n≤10^5 1≤m≤10^6)接下来n行每行两个整数x y表示每个城市的坐标。(|x|,|y|≤10^6)接下来m行描述一条不能走的道路(起点和终点)。数据保证有解。

Output

输出一个实数,最短距离,误差10^-5以内均算正确。

Sample Input

6 9
-12 -10
-11 6
-4 12
6 14
16 6
18 -2
3 4
1 5
2 6
2 3
4 5
3 5
1 3
3 6
1 6

Sample Output

42.000000000

HINT

 

Source

 
先瞎BB几句,习惯不看背景的我,一眼看过去以为是求补图的最短路。论审题的重要性。
想法:
根据“道路相交处可以自由穿行。”,然后画图发现。可以把所有合法的路拿出来,把包含1,n的那面作为合法面。这样做一遍半平面交,得到凸多边形的周长就是答案。O(n^2logn)
然后根据“XXX岛屿是一个凸多边形。”,距离最短的合法路肯定是终点编号大的。所以每个点最多只要取一条路就好了。O(nlogn)
 
#include<cmath>
#include<cstdio>
#include<vector>
#include<algorithm> const int len();
const double eps(1e-);
struct Coor//向量或点
{
double x,y;
Coor(){};
Coor(double a,double b):x(a),y(b){};
inline Coor operator +(const Coor&a)const{return Coor(x+a.x,y+a.y);}
inline Coor operator -(const Coor&a)const{return Coor(x-a.x,y-a.y);}
inline Coor operator *(const double&k)const{return Coor(x*k,y*k);}
inline Coor operator /(const double&k)const{return Coor(x/k,y/k);}
}pr[len+],ie[len+];int tot;
double dot(Coor a,Coor b){return a.x*b.x+a.y*b.y;}//点积
double cross(Coor a,Coor b){return a.x*b.y-a.y*b.x;}//叉积
struct Line
{
Coor a,b;//直线上两个点a->b,钦点半平面交均保留向量左手方向。
double angle;
Line(){};
Line(Coor A,Coor B,double a):a(A),b(B),angle(a){};
Coor intersect(Line &B)
{
double s1=cross(B.a-a,B.b-a),s2=cross(B.b-b,B.a-b);//面积的方向
return a+(b-a)*s1/(s1+s2);
}
void getAngle(){angle=atan2(b.y-a.y,b.x-a.x);}
}L[len+];int up;
int n,m,x,y;long double ans;
std::vector<int>Edge[len+];
void swap(int &x,int &y){x^=y,y^=x,x^=y;}
int dcmp(double x){return x<-eps?-:x>eps;}
bool cmp(Line A,Line B)
{
double c=A.angle-B.angle;
int d=dcmp(c);
if(d)return d>;//逆时针,事实证明这里正着反着都一样。
c=cross(A.b-A.a,B.b-A.a);//保留左手方向
return c<-eps;
}
bool jud(Line p1,Line p2,Line p3)
{
Coor p=p1.intersect(p2);
double c=cross(p3.b-p3.a,p-p3.a);
return dcmp(c)<;
}
void deal()
{
int _up=;
for(int i=;i<=up;i++)if(dcmp(L[i-].angle-L[i].angle))L[++_up]=L[i];
up=_up;
}
long double sqr(long double x){return x*x;}
long double dis(Coor A,Coor B)
{
return sqrt(sqr(A.x-B.x)+sqr(A.y-B.y));
}
int que[len+],head,tail;
void SI()
{
std::sort(L+,L++up,cmp);//排序可能会打乱顺序
deal();
que[]=;que[]=;head=;tail=;
for(int i=;i<=up;i++)
{
while(head<tail && jud(L[que[tail-]],L[que[tail]],L[i]))
tail--;
while(head<tail && jud(L[que[head+]],L[que[head]],L[i]))
head++;
que[++tail]=i;
}
while(head<tail- && jud(L[que[tail-]],L[que[tail]],L[que[head]]))
tail--;
while(head+<tail && jud(L[que[head+]],L[que[head]],L[que[tail]]))
head++;
que[tail+]=que[head];
for(int i=head;i<=tail;i++)ie[++tot]=L[que[i]].intersect(L[que[i+]]);
ie[tot+]=ie[];
for(int i=;i<=tot;i++)ans+=dis(ie[i],ie[i+]);
ans-=dis(pr[],pr[n]);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%lf %lf",&pr[i].x,&pr[i].y);
for(int i=;i<=m;i++)
{
scanf("%d %d",&x,&y);
if(x>y)swap(x,y);
Edge[x].push_back(y);
}
for(int i=,j;i<n;i++)
{
std::sort(Edge[i].begin(),Edge[i].end());
j=n;
while(Edge[i].size()&&Edge[i].back()==j&&j>i)
j--,Edge[i].pop_back();
if(j>i)L[++up]=Line(pr[j],pr[i],);//逆时针
if(i==&&j==n)ans=dis(pr[],pr[n]);
}
if(ans){printf("%.10Lf\n",ans);return ;}
L[++up]=Line(pr[],pr[n],);
for(int i=;i<=up;i++)L[i].getAngle();
SI();
printf("%.10Lf\n",ans);
return ;
}

BZOJ 1137: [POI2009]Wsp 岛屿 半平面交的更多相关文章

  1. bzoj 1137 [POI2009]Wsp 岛屿

    题目大意 Byteotia岛屿是一个凸多边形.城市全都在海岸上.按顺时针编号1到n.任意两个城市之间都有一条笔直的道路相连.道路相交处可以自由穿行.有一些道路被游击队控制了,不能走,但是可以经过这条道 ...

  2. BZOJ 1038 ZJOI2008 瞭望塔 半平面交

    题目大意及模拟退火题解:见 http://blog.csdn.net/popoqqq/article/details/39340759 这次用半平面交写了一遍--求出半平面交之后.枚举原图和半平面交的 ...

  3. bzoj 4445 小凸想跑步 - 半平面交

    题目传送门 vjudge的快速通道 bzoj的快速通道 题目大意 问在一个凸多边形内找一个点,连接这个点和所有顶点,使得与0号顶点,1号顶点构成的三角形是最小的概率. 假设点的位置是$(x, y)$, ...

  4. bzoj 3190 赛车 半平面交

    直接写的裸的半平面交,已经有点背不过模板了... 这题卡精度,要用long double ,esp设1e-20... #include<iostream> #include<cstd ...

  5. BZOJ 4445 [Scoi2015]小凸想跑步:半平面交

    传送门 题意 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸 $ n $ 边形,$ n $ 个顶点 $ P_i $ 按照逆时针从 $ 0 $ 至 $ n-1 $ 编号. ...

  6. BZOJ 1829 [Usaco2010 Mar]starc星际争霸 ——半平面交

    发现最终的结果只和$s1$,$s2$,$s3$之间的比例有关. 所以直接令$s3=1$ 然后就变成了两个变量,然后求一次半平面交. 对于每一个询问所属的直线,看看半平面在它的那一侧,或者相交就可以判断 ...

  7. 【BZOJ-4515】游戏 李超线段树 + 树链剖分 + 半平面交

    4515: [Sdoi2016]游戏 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 304  Solved: 129[Submit][Status][ ...

  8. poj3335 半平面交

    题意:给出一多边形.判断多边形是否存在一点,使得多边形边界上的所有点都能看见该点. sol:在纸上随手画画就可以找出规律:按逆时针顺序连接所有点.然后找出这些line的半平面交. 题中给出的点已经按顺 ...

  9. POJ3525 半平面交

    题意:求某凸多边形内部离边界最远的点到边界的距离 首先介绍半平面.半平面交的概念: 半平面:对于一条有向直线,它的方向的左手侧就是它所划定的半平面范围.如图所示: 半平面交:多个半平面的交集.有点类似 ...

随机推荐

  1. 二十五种网页加速方法和seo优化技巧

    一.使用良好的结构 可扩展 HTML (XHTML) 具有许多优势,但是其缺点也很明显.XHTML 可能使您的页面更加符合标准,但是它大量使用标记(强制性的 <start> 和 <e ...

  2. Java8函数式接口之Predicate<T>

    作用: 这是一个功能接口,因此可以作为lambda表达式或方法引用的赋值目标. 实例: /** * Created by luo on 2017/5/3. */ public class Predic ...

  3. Linux系统下使用split命令分割大文件 (转载)

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://snailwarrior.blog.51cto.com/680306/140531 ...

  4. matplotlib画线(2)

    这篇随笔是matplotlib画线的补充>>> #nocl参数控制图例中有几列,>>> import numpy as np>>> import ...

  5. [51nod] 1091 线段的重叠 贪心

    X轴上有N条线段,每条线段包括1个起点和终点.线段的重叠是这样来算的,[10 20]和[12 25]的重叠部分为[12 20]. 给出N条线段的起点和终点,从中选出2条线段,这两条线段的重叠部分是最长 ...

  6. Unity5 AssetBundle资源管理架构设计

    http://blog.csdn.net/qq_19399235/article/details/51702964 1:Unity5 资源管理架构设计(2017.4.22版本) 2:Android 热 ...

  7. Unity开发Android应用优化指南(上)

    http://forum.china.unity3d.com/thread-27037-1-2.html 如今越来越多的开发者使用Unity开发Android及iOS项目,开发过程中难免会遇到一些性能 ...

  8. VMware Workstation “无法连接 MKS: 套接字连接尝试次数太多;正在放弃。” 解决方法【转】

    今天和往常一样打开电脑,打开VMware Workstation,打开其中的一台虚拟机,以前都是这么打开没有问题,今天打开虚拟机突然提示“无法连接 MKS: 套接字连接尝试次数太多:正在放弃.”. 经 ...

  9. 图像像素灰度内插(Matlab实现)

    常用的像素灰度内插法:最近邻元法.双线性内插法.三次内插法 %%像素灰度内插 factor = 0.75;%缩放比 u = 0.6;v = 0.7; itp1 = uint8(zeros(ceil(h ...

  10. Eclipse中各图标含义

    Eclipse中定义很多小图标,在平时的开发工作中,熟悉这些小图标还是很有意义的.那具体意义大家又知道多少呢? 首先,通过在搜索“eclipse icon meaning”,找到了一个比较有用的链接, ...