正题

题目链接: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】的更多相关文章

  1. 7.1 NOI模拟赛 凸包套凸包 floyd 计算几何

    计算几何之所以难学 就是因为太抽象了 不够直观 而且情况很多 很繁琐 甚至有一些东西不清不楚.. 这道题注意到题目中的描述 一个鸽子在两个点所连直线上也算. 通过看题解 发现这个地方并非直线而是线段 ...

  2. 【BZOJ】1027: [JSOI2007]合金(凸包+floyd)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1027 题意:$n$种材料,$m$种需求.每种材料有三个属性,给出三个属性的含量(和为1),问能否通过 ...

  3. 【BZOJ 1027】 (凸包+floyd求最小环)

    [题意] 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的原材料中铁铝锡的比重不同.然后,将每种原材料取出一定量,经过融解.混合,得到新的合金.新的合金 ...

  4. bzoj 1027: [JSOI2007]合金【凸包+Floyd】

    参考:https://www.cnblogs.com/zhuohan123/p/3237246.html 因为一c可以由1-a-b得出,所以删掉c,把a,b抽象成二维平面上的点.首先考虑一个客户需求能 ...

  5. 【BZOJ】【1027】【JSOI2007】合金

    计算几何/凸包/Floyd Orz rausen大爷太强辣 计算几何题目果然不会做>_> 这个题……虽然他给了3个坐标,但实际上是个二维的计算几何题= =因为第三维坐标可以直接用前两维坐标 ...

  6. 【JZOJ5094】【GDSOI2017第四轮模拟day3】鸽子 计算几何+floyd

    题面 养鸽人要监视他的鸽子,有n只鸽子站在平面上,他可以在m个给定的点上设置监视器,如果一只鸽子在某个监视器上或者在两个监视器所连直线上或者在三个监视器所连直线的三角形内则其就咕咕咕了,现在养鸽人要让 ...

  7. BZOJ1390 CEOI2008 Fences 凸包、Floyd最小环/DP

    传送门 为了方便描述把固定点叫做白色点,Tree叫做黑色点 一种基于特殊性质的做法: 如果不算入选白色的权值,那么一定会选中所有白色点构成的凸包上的点,因为能够尽可能围更多的黑色点.然后我们在这个基础 ...

  8. HDU - 6080 :度度熊保护村庄 (凸包,floyd最小环)(VJ1900题达成)

    pro:二维平面上,给定N个村庄.M个士兵驻守,把村庄围住,现在我们想留下更多的士兵休息,使得剩下的士兵任然满足围住村庄.N,M<500: sol:即是要找一个最小的环,环把村庄围住. 由于是环 ...

  9. bzoj 1027 [JSOI2007]合金(计算几何+floyd最小环)

    1027: [JSOI2007]合金 Time Limit: 4 Sec  Memory Limit: 162 MBSubmit: 2970  Solved: 787[Submit][Status][ ...

随机推荐

  1. TP6 服务器响应500时没有错误信息的解决方案

    重点!!!! 首先,确认你的电脑管理员账户是否含有中文!!!!!!就像下面这种:所以出现了没有错误提示    查看nginx日志显示\vendor\topthink\framework\src\thi ...

  2. Vue 如何实现一个底部导航栏组件

    参考网址: https://www.jianshu.com/p/088936b7b1bd/ Vue 如何实现一个底部导航栏组件 可以看到父组件是知道我点击了底部TabBar的哪个item的. 实现 实 ...

  3. 【spring 注解驱动开发】spring ioc 原理

    尚学堂spring 注解驱动开发学习笔记之 - Spring容器创建 Spring容器创建 1.Spring容器创建-BeanFactory预准备 2.Spring容器创建-执行BeanFactory ...

  4. Redis Jedis lua脚本

    参考:http://redisdoc.com/script/eval.htmlhttps://blog.csdn.net/diudiu2025/article/details/86483043fina ...

  5. linux 常用命令(三)——(centos7)MySql 5.7添加用户、删除用户与授权

    一.创建用户:以root用户登录到数据库进行用户创建 命令: CREATE USER 'username'@'host' IDENTIFIED BY 'password'; 例如: CREATE US ...

  6. JAVA中的策略模式strategy

    原文出自:http://ttitfly.iteye.com/blog/136467 1. 以一个算术运算为例,传统做法为: java 代码 package org.common; public cla ...

  7. validity属性返回对象中的属性值

  8. docker开启remote-api 2375端口后,Failed to start Docker Application Container Engine,重启docker失败的问题解决

    1.  按照网上的教程修改了 /usr/lib/systemd/system/docerk.service配置后,重启失败.修改/etc/docker/daemon.json 增加hosts后重启也是 ...

  9. jvm学习笔记:栈帧

    栈帧内的数据结构 局部变量表(Local Variables):记录非静态方法的this指针.方法参数.局部变量 操作数栈(Operand Stack):用于计算的栈结构 动态链接(Dynamic L ...

  10. 7-31 堆栈操作合法性 (20 分) PTA

    7-31 堆栈操作合法性 (20 分)   假设以S和X分别表示入栈和出栈操作.如果根据一个仅由S和X构成的序列,对一个空堆栈进行操作,相应操作均可行(如没有出现删除时栈空)且最后状态也是栈空,则称该 ...