bzoj1137【POI2009】Wsp 岛屿

1137: [POI2009]Wsp 岛屿

Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge

Submit: 75  Solved: 38

[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

鸣谢 vfleaking

半平面交思路好题

因为1-n是顺时针排列,所以1-n的最短路径就是所有可以使用的线段的半平面交的长度。

然而这样也是不行的因为边最多会有O(n^2)条。

每个点出发的点,一定是越靠后越好,所以只要保存最靠后那条,这样边就只有O(n)条了。

#include<iostream>
#include<cstdlib>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 100005
#define maxm 1000005
#define eps 1e-8
using namespace std;
int n,m,cnt,tot;
double ans;
struct P
{
	double x,y;
	P(double xx=0,double yy=0){x=xx;y=yy;}
	friend P operator -(P a,P b){return P(a.x-b.x,a.y-b.y);}
	friend double operator *(P a,P b){return a.x*b.y-a.y*b.x;}
}p[maxn],a[maxn];
struct L
{
	P a,b;double angle;
	friend bool operator <(L a,L b)
	{
		if (fabs(a.angle-b.angle)<=eps) return (a.b-a.a)*(b.b-a.a)>0;
		else return a.angle<b.angle;
	}
}l[maxn],q[maxn];
struct edge
{
	int x,y;
	friend bool operator <(edge a,edge b){return a.x==b.x?a.y>b.y:a.x<b.x;}
}e[maxm];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline double dis(P a,P b)
{
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline P inter(L l1,L l2)
{
	double k1=(l2.b-l1.a)*(l1.b-l1.a),k2=(l1.b-l1.a)*(l2.a-l1.a),t=k1/(k1+k2);
	return P(l2.b.x+(l2.a.x-l2.b.x)*t,l2.b.y+(l2.a.y-l2.b.y)*t);
}
inline bool judge(L l1,L l2,L t)
{
	P p=inter(l1,l2);
	return (t.b-t.a)*(p-t.a)<-eps;
}
inline void hpi()
{
	F(i,1,cnt) l[i].angle=atan2(l[i].b.y-l[i].a.y,l[i].b.x-l[i].a.x);
	sort(l+1,l+cnt+1);
	int head=1,tail=0;tot=1;
	F(i,2,cnt)
	{
		if (fabs(l[i].angle-l[i-1].angle)>=eps) tot++;
		l[tot]=l[i];
	}
	cnt=tot;
	q[++tail]=l[1];q[++tail]=l[2];
	F(i,3,cnt)
	{
		while (head<tail&&judge(q[tail],q[tail-1],l[i])) tail--;
		while (head<tail&&judge(q[head],q[head+1],l[i])) head++;
		q[++tail]=l[i];
	}
	while (head<tail&&judge(q[tail],q[tail-1],q[head])) tail--;
	tot=0;
	F(i,head,tail-1) a[++tot]=inter(q[i],q[i+1]);
	a[++tot]=inter(q[head],q[tail]);
}
int main()
{
	n=read();m=read();
	F(i,1,n) p[i].x=read(),p[i].y=read();
	F(i,1,m)
	{
		e[i].x=read();e[i].y=read();
		if (e[i].x>e[i].y) swap(e[i].x,e[i].y);
	}
	sort(e+1,e+m+1);
	if (e[1].x!=1||e[1].y!=n)
	{
		printf("%.10lf\n",dis(p[1],p[n]));
		return 0;
	}
	int t=1;
	F(i,1,n-1)
	{
		int j=n;
		while (t<=m&&e[t].x==i&&e[t].y==j&&j>i) j--,t++;
		if (j>i) l[++cnt]=(L){p[j],p[i]};
		while (t<=m&&e[t].x==i) t++;
	}
	l[++cnt]=(L){p[1],p[n]};
	hpi();
	a[0]=a[tot];
	F(i,1,tot) ans+=dis(a[i],a[i-1]);
	ans-=dis(p[1],p[n]);
	printf("%.10lf\n",ans);
	return 0;
}
时间: 2024-08-24 12:52:31

bzoj1137【POI2009】Wsp 岛屿的相关文章

BZOJ 1137: [POI2009]Wsp 岛屿 半平面交

1137: [POI2009]Wsp 岛屿 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 165  Solved: 78[Submit][Status][Discuss] Description Byteotia岛屿是一个凸多边形.城市全都在海岸上.按顺时针编号1到n.任意两个城市之间都有一条笔直的道路相连.道路相交处可以自由穿行.有一些道路被游击队控制了,不能走,但是可以经过这条道路与未被控制的道路的交点.问

省选之前的未完成的计划(截至到省选)

PLAN OF THE COMING HEOI good problems:-bzoj4823:[Cqoi2017]老C的方块 [*]-bzoj3171:[Tjoi2013]循环格 [*]-bzoj4200:[Noi2015]小园丁与老司机 [*]-bzoj1061:[Noi2008]志愿者招募 [*]-bzoj3600:没有人的算术 [*]-bzoj2806:[Ctsc2012]Cheat [*]-bzoj2219:数论之神 [*]-bzoj2595:[Wc2008]游览计划 [*]-bzoj

东方14模拟赛之岛屿

02:岛屿 查看 提交 统计 提问 总时间限制:  40000ms 单个测试点时间限制:  4000ms 内存限制:  128000kB 描述 从前有一座岛屿,这座岛屿是一个长方形,被划为N*M的方格区域,每个区域都有一个确定的高度.不幸的是海平面开始上涨,在第i年,海平面的高度为t[i].如果一个区域的高度小于等于海平面高度,则视为被淹没.那些没有被淹没的连通的区域够成一个连通块.现在问第i年,这样的连通块有多少个. 例如:第一年海平面高度为1,有2个连通块. 第二年海平面高度为2,有3个连通

【BZOJ 1119】 1119: [POI2009]SLO (置换)

1119: [POI2009]SLO Description 对于一个1-N的排列(ai),每次你可以交换两个数ax与ay(x<>y),代价为W(ax)+W(ay) 若干次交换的代价为每次交换的代价之和.请问将(ai)变为(bi)所需的最小代价是多少. Input 第一行N.第二行N个数表示wi.第三行N个数表示ai.第四行N个数表示bi. 2<=n<=1000000 100<=wi<=6500 1<=ai,bi<=n ai各不相等,bi各不相等 (ai)&

51nod 1276 1276 岛屿的数量 (很好玩的题目

题意: 有N个岛连在一起形成了一个大的岛屿,如果海平面上升超过某些岛的高度时,则这个岛会被淹没.原本的大岛屿则会分为多个小岛屿,如果海平面一直上升,则所有岛都会被淹没在水下. 给出N个岛的高度.然后有Q个查询,每个查询给出一个海平面的高度H,问当海平面高度达到H时,海上共有多少个岛屿.例如: 岛屿的高度为:{2, 1, 3, 2, 3}, 查询为:{0, 1, 3, 2}. 当海面高度为0时,所有的岛形成了1个岛屿. 当海面高度为1时,岛1会被淹没,总共有2个岛屿{2} {3, 2, 3}. 当

nyoj 1237 最大岛屿(dfs)

描述 神秘的海洋,惊险的探险之路,打捞海底宝藏,激烈的海战,海盗劫富等等.加勒比海盗,你知道吧?杰克船长驾驶着自己的的战船黑珍珠1号要征服各个海岛的海盜,最后成为海盗王. 这是一个由海洋.岛屿和海盗组成的危险世界.面对危险重重的海洋与诡谲的对手,如何凭借智慧与运气,建立起一个强大的海盗帝国. 杰克船长手头有一张整个海域的海图,上面密密麻麻分布着各个海屿的位置及面积.他想尽快知道整个海域共有多少岛屿以及最大岛屿的面积. 输入 第1行:M N T,表示海域的长,宽及一个单位表示的面积大小 接下来有M

岛屿的个数

|题目 给一个01矩阵,求不同的岛屿的个数. 0代表海,1代表岛,如果两个1相邻,那么这两个1属于同一个岛.我们只考虑上下左右为相邻. |在线测试本题 http://www.lintcode.com/zh-cn/problem/number-of-islands/ |难度 容易

BZOJ1119: [POI2009]SLO

1119: [POI2009]SLO Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 379  Solved: 181[Submit][Status] Description 对于一个1-N的排列(ai),每次你可以交换两个数ax与ay(x<>y),代价为W(ax)+W(ay) 若干次交换的代价为每次交换的代价之和.请问将(ai)变为(bi)所需的最小代价是多少. Input 第一行N. 第二行N个数表示wi. 第三行N个数表示ai. 第四行N个

BZOJ 1115: [POI2009]石子游戏Kam

1115: [POI2009]石子游戏Kam Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 924  Solved: 574[Submit][Status][Discuss] Description 有N堆石子,除了第一堆外,每堆石子个数都不少于前一堆的石子个数.两人轮流操作每次操作可以从一堆石子中移走任意多石子,但是要保证操作后仍然满足初始时的条件谁没有石子可移时输掉游戏.问先手是否必胜. Input 第一行u表示数据组数.对于每组数据,第一行