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. HDU - 6025 Coprime Sequence(gcd+前缀后缀)

    Do you know what is called ``Coprime Sequence''? That is a sequence consists of nnpositive integers, ...

  2. JS实现页面刷新方法

    下面介绍全页面刷新方法:有时候可能会用到 window.location.reload()刷新当前页面. parent.location.reload()刷新父亲对象(用于框架) opener.loc ...

  3. 如何让div中的span垂直居中 ----height:100%设置div的高度

    如果div中只有一个span一个元素,可以使用line-height.如果div中还有其他元素,可以设置span的css如下: .span{ position: absolute; top: 50%; ...

  4. 安装 Twisted 解决ImportError: No module named zope.interface错误

    转自:http://blog.csdn.net/mickey_miki/article/details/7911323 步骤1:下载Twisted http://twistedmatrix.com/t ...

  5. 最棒的Unity Github 项目收集(2016)

    http://1darray.com/blog/2016/03/08/best-unity-github-repositories/ List of best public GitHub reposi ...

  6. tableview中用动画效果改变cell的高度

    我们要的效果大概就是如下效果: 当我们选择一个cell的时候,我们就要改变它的高度,并且以动画的形式. 我们该如何实现这个效果呢?我们主要需要使用以下这两个方法: - (CGFloat)tableVi ...

  7. 11.Python初窥门径(函数名,可迭代对象,迭代器)

    Python(函数名,可迭代对象,迭代器) 一.默认参数的坑 # 比较特殊,正常来说临时空间执行结束后应该删除,但在这里不是. def func(a,l=[]): l.append(a) return ...

  8. BZOJ 1069: [SCOI2007]最大土地面积(旋转卡壳)

    题目链接~ 1069: [SCOI2007]最大土地面积 思路很简单,极角排序求完凸包后,在凸包上枚举对角线,然后两边分别来两个点旋转卡壳一下,搞定! 不过计算几何的题目就是这样,程序中间的处理还是比 ...

  9. layui实现下拉分类多级

    Layui tree 下拉菜单树   1.效果: 2.html  代码: <!DOCTYPE html> <html> <head> <meta charse ...

  10. 洛谷 P1434 [SHOI2002]滑雪 解题报告

    这题方法有很多, 这里介绍2种: 方法1 很容易想到搜索, bfs或dfs应该都可以, 就不放代码了: 方法2 这题还可以用 dp 来做. 做法:先将每个点按照高度从小到大排序,因为大的点只能向小的点 ...