YbtOJ#832-鸽子饲养【凸包,Floyd】
正题
题目链接:https://www.ybtoj.com.cn/contest/116/problem/3
题目大意
给出两个大小分别为\(n,m\)的点集\(A,B\)。
求出\(B\)的一个最小子集使得该子集的凸包包含了所有点集\(A\)中的点。
无解输出\(-1\)
\(2\leq n\leq 10^5,3\leq m\leq 500\)
解题思路
选出的子集肯定是一个凸包,凸包就是相邻点连边之间的半平面交。
所以可以理解为我们要找到一些点对使得它们的半平面包含点集\(A\)。
如果\(x->y\)的半平面(左右都一样,反过来就是了)包含点集\(A\),那么\(x\)向\(y\)连边,那么问题就变为了求图的最小环。这个可以\(Floyd\)解决。
如何判断一个半平面是否包含点集\(A\)?
一个类似旋转卡壳的想法是对于给出的这个半平面的斜率,我们在点集\(A\)的凸包上找到两个节点卡住它。(如下图)

然后判断这两个点是否在半平面内就好了。
挺麻烦的,再简化一下,我们将\(A\)的凸包用\(x\)坐标最大/小的两个节点分成两半,那么凸包就变成了一个上凸壳和一个下凸壳。
然后我们要找到的两个点,这个两个点肯定是一个在上一个在下的,我们根据半平面的斜率在上下凸壳上面二分一下就好了。
时间复杂度\(O(n+m^2\log n+m^3)\)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1e5+10,M=510;
struct point{
ll x,y;
point(ll xx=0,ll yy=0)
{x=xx;y=yy;return;}
}g[N],u[N],v[N],s[N],p[M];
ll n,m,uc,vc,f[M][M],h[M][M],ans;
point operator+(point a,point b)
{return point(a.x+b.x,a.y+b.y);}
point operator-(point a,point b)
{return point(a.x-b.x,a.y-b.y);}
ll operator*(point a,point b)
{return a.x*b.y-a.y*b.x;}
ll solve(point *a,ll n,ll op){
ll top;s[top=1]=a[1];
for(ll i=2;i<=n;i++){
while(top>1&&(s[top]-s[top-1])*(a[i]-s[top-1])*op>=0)top--;
s[++top]=a[i];
}
for(ll i=1;i<=top;i++)
a[i]=s[i];
return top;
}
bool check(point a,point b){
ll op=1;
if(a.x>b.x)swap(a,b),op=-1;
ll l=1,r=uc-1;
while(l<=r){
ll x=(l+r)>>1;
if((b-a)*(u[x+1]-u[x])>=0)l=x+1;
else r=x-1;
}
if((b-a)*(u[l]-a)*op<0)return 0;
l=1,r=vc-1;
while(l<=r){
ll x=(l+r)>>1;
if((b-a)*(v[x+1]-v[x])<=0)l=x+1;
else r=x-1;
}
if((b-a)*(v[l]-a)*op<0)return 0;
return 1;
}
bool cmp(point a,point b)
{return a.x<b.x;}
signed main()
{
freopen("lo.in","r",stdin);
freopen("lo.out","w",stdout);
scanf("%lld%lld",&n,&m);
ll L=1,R=1;
for(ll i=1;i<=n;i++)
scanf("%lld%lld",&g[i].x,&g[i].y);
sort(g+1,g+1+n,cmp);
for(ll i=1;i<=n;i++){
ll w=(g[n]-g[1])*(g[i]-g[1]);
if(w>=0)u[++uc]=g[i];
if(w<=0)v[++vc]=g[i];
}
uc=solve(u,uc,1);
vc=solve(v,vc,-1);
for(ll i=1;i<=m;i++)
scanf("%lld%lld",&p[i].x,&p[i].y);
for(ll i=1;i<=m;i++)
for(ll j=1;j<=m;j++){
if(i==j){h[i][j]=f[i][j]=1e9;continue;}
h[j][i]=f[i][j]=check(p[i],p[j])?1:1e9;
}
for(ll k=1;k<=m;k++)
for(ll i=1;i<=m;i++)
for(ll j=1;j<=m;j++)
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
ans=1e9;
for(ll i=1;i<=m;i++)
for(ll j=1;j<=m;j++)
ans=min(ans,f[i][j]+h[i][j]);
if(ans>=1e9)puts("-1");
else printf("%lld\n",ans);
return 0;
}
YbtOJ#832-鸽子饲养【凸包,Floyd】的更多相关文章
- 7.1 NOI模拟赛 凸包套凸包 floyd 计算几何
计算几何之所以难学 就是因为太抽象了 不够直观 而且情况很多 很繁琐 甚至有一些东西不清不楚.. 这道题注意到题目中的描述 一个鸽子在两个点所连直线上也算. 通过看题解 发现这个地方并非直线而是线段 ...
- 【BZOJ】1027: [JSOI2007]合金(凸包+floyd)
http://www.lydsy.com/JudgeOnline/problem.php?id=1027 题意:$n$种材料,$m$种需求.每种材料有三个属性,给出三个属性的含量(和为1),问能否通过 ...
- 【BZOJ 1027】 (凸包+floyd求最小环)
[题意] 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的原材料中铁铝锡的比重不同.然后,将每种原材料取出一定量,经过融解.混合,得到新的合金.新的合金 ...
- bzoj 1027: [JSOI2007]合金【凸包+Floyd】
参考:https://www.cnblogs.com/zhuohan123/p/3237246.html 因为一c可以由1-a-b得出,所以删掉c,把a,b抽象成二维平面上的点.首先考虑一个客户需求能 ...
- 【BZOJ】【1027】【JSOI2007】合金
计算几何/凸包/Floyd Orz rausen大爷太强辣 计算几何题目果然不会做>_> 这个题……虽然他给了3个坐标,但实际上是个二维的计算几何题= =因为第三维坐标可以直接用前两维坐标 ...
- 【JZOJ5094】【GDSOI2017第四轮模拟day3】鸽子 计算几何+floyd
题面 养鸽人要监视他的鸽子,有n只鸽子站在平面上,他可以在m个给定的点上设置监视器,如果一只鸽子在某个监视器上或者在两个监视器所连直线上或者在三个监视器所连直线的三角形内则其就咕咕咕了,现在养鸽人要让 ...
- BZOJ1390 CEOI2008 Fences 凸包、Floyd最小环/DP
传送门 为了方便描述把固定点叫做白色点,Tree叫做黑色点 一种基于特殊性质的做法: 如果不算入选白色的权值,那么一定会选中所有白色点构成的凸包上的点,因为能够尽可能围更多的黑色点.然后我们在这个基础 ...
- HDU - 6080 :度度熊保护村庄 (凸包,floyd最小环)(VJ1900题达成)
pro:二维平面上,给定N个村庄.M个士兵驻守,把村庄围住,现在我们想留下更多的士兵休息,使得剩下的士兵任然满足围住村庄.N,M<500: sol:即是要找一个最小的环,环把村庄围住. 由于是环 ...
- bzoj 1027 [JSOI2007]合金(计算几何+floyd最小环)
1027: [JSOI2007]合金 Time Limit: 4 Sec Memory Limit: 162 MBSubmit: 2970 Solved: 787[Submit][Status][ ...
随机推荐
- WPF QQ群发助手
一.界面如下
- NameNode&Secondary NameNode 工作机制
NameNode&Secondary NameNode 工作机制 NameNode: 1.启动时,加载编辑日志和镜像文件到内存 2.当客户端对元数据进行增删改,请求NameNode 3.Nam ...
- 信号量-Semaphore、SemaphoreSlim
核心类:Semaphore,通过int数值来控制线程个数. * 通过观察构造函数 public Semaphore(int initialCount, int maximumCount);: * in ...
- jdbc获取PreparedStatement最终执行的sql语句
//直接打印PreparedStatement对象 System.out.println(ps); 输出结果: com.mysql.jdbc.JDBC42PreparedStatement@5f205 ...
- restore db fail
System.Data.SqlClient.SqlError: The operating system returned the error '5(Access is denied.)' while ...
- linux centos7 df命令
2021-08-04 1. df 命令简介 linux 中 df 命令的功能是用来检查 linux 服务器的文件系统的磁盘空间占用情况.可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间等信 ...
- FeignClient注解属性configuration不生效问题排查思路
FeignClient注解属性configuration不生效问题排查思路 问题背景 我们知道,"如果需要自定义单个Feign配置,Feign的@Configuration 注解的类不能与@ ...
- BeanUtils基本使用方法与原理
使用BeanUtils的原因 因为setProperty是JSP中的标签,因此使用model 2模式JSP+Servlet+JavaBean的时候,JSP将form提交给Servlet程序,而Serv ...
- Sentry For React 完整接入详解(2021 Sentry v21.8.x)前方高能预警!三万字,慎入!
内容源于:https://docs.sentry.io/platforms/javascript/guides/react/ 系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - ...
- Docker容器管理——运行容器命令
1.容器的生命周期(***重要,需要理解) 容器启动后,执行的第一条命令的PID为1 ========================>>>>>>>& ...