正题

题目链接: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. HashTable原理和底层实现

    1. 概述 上次讨论了HashMap的结构,原理和实现,本文来对Map家族的另外一个常用集合HashTable进行介绍.HashTable和HashMap两种集合非常相似,经常被各种面试官问到两者的区 ...

  2. C语言之----面向对象的方法实现链表的操作

    1 /* 2 * 详细运行过程: 本程序实现的是对链表的简单的操作,即链表的增 删 改 查 销毁 初始化 3 * 运用面向对象的思想,实现一个类op,op中包括了所有的链表操作方法 4 * 其他的程序 ...

  3. IO异常--缓冲流--转换流--序列化流( IO流2 )

    1.IO异常的处理 JDK7前处理:使用try...catch...finally 代码块,处理异常部分 // 声明变量 FileWriter fw = null; try { //创建流对象 fw ...

  4. python常用工具库介绍

    Numpy:科学计算 HOME:  http://www.numpy.org/ NumPy is the fundamental package for scientific computing wi ...

  5. MySQL alter table时执行innobackupex全备再看Seconds_Behind_Master

    1.场景描述 早上7:25 接到Report中心同学告警,昨天业务报表数据没有完整跑出来,缺少500位业务员的数据,并且很快定位到,缺少的是huabei_order库上的数据.Report中心的数据是 ...

  6. MySQL-SQL基础1

    p.p1 { margin: 0; font: 11px Menlo; background-color: rgba(128, 128, 128, 0.5); min-height: 13px } p ...

  7. Java 学习:对象和类

    对象和类 从认识的角度考虑是先有对象后有类.对象,是具体的事物.类,是抽象的,是对对象的抽象. 从代码运行角度考虑是先有类后又对象.类是对象的模板. 对象:对象是类的一个实例,有状态和行为. 类:类是 ...

  8. vue 封装 axios 和 各类的请求,以及引入 .vue 文件中使用

    //src 底下建立 api 文件夹 // api 文件夹下建立 request,js 文件,文件内容复制下面这段代码即可   /**  * ajax请求配置  */ import axios fro ...

  9. Vue Router路由导航及传参方式

    路由导航及传参方式 一.两种导航方式 ①:声明式导航 <router-link :to="..."> ②:编程式导航 router.push(...) 二.编程式导航参 ...

  10. chrome插件开发学习(一)

    两个不错的网址: 360chrome插件开发文档:http://open.chrome.360.cn/extension_dev/manifest.html 图灵 chrome插件开发于应用 电子书: ...