【BZOJ5316】[JSOI2018]绝地反击(网络流,计算几何,二分)

题面

BZOJ
洛谷

题解

很明显需要二分一个答案。
那么每个点可以确定的范围就是以当前点为圆心,二分出来的答案为半径画一个圆,和目标的圆的交就是可行的区间。
首先我们不知道正\(n\)边形的转角,如果我们知道的话,可以直接暴力网络流来进行\(check\)。
首先一个答案可行,意味着某个点在目标圆上覆盖的弧的两端中,一定有一个是可行的。
所以我们需要验证的转角只有\(2n\)个。这样子暴力跑网络流的次数是\(2nlogn\)次。
考虑如何优化这个过程。
发现合法的转角一共\(2n\)个,把它们按照转角排序,考虑从小往大改变转角的过程,显然每次会删掉一个可行的匹配,或者是加入一组可行的匹配。
那么这里删边直接退流就好了,不需要每次构图重建。
因为是二分图,退流直接手动删边就行了。
加边直接加完之后重新增广一次就行了。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
#define MAX 605
const double Pi=acos(-1),eps=1e-8;
const int inf=1000000000;
inline int read()
{int x=0;bool t=false;char ch=getchar();while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();if(ch=='-')t=true,ch=getchar();while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();return t?-x:x;
}
int n,R,S,T;
struct Line{int v,next,w;}e[MAX*MAX];
int h[MAX],cnt=2,cur[MAX];
inline void Add(int u,int v,int w)
{e[cnt]=(Line){v,h[u],w};h[u]=cnt++;e[cnt]=(Line){u,h[v],0};h[v]=cnt++;
}
int level[MAX];
bool bfs()
{for(int i=S;i<=T;++i)level[i]=0;for(int i=S;i<=T;++i)cur[i]=h[i];queue<int> Q;level[S]=1;Q.push(S);while(!Q.empty()){int u=Q.front();Q.pop();for(int i=h[u];i;i=e[i].next)if(e[i].w&&!level[e[i].v])level[e[i].v]=level[u]+1,Q.push(e[i].v);}return level[T];
}
int dfs(int u,int flow)
{if(u==T||!flow)return flow;int ret=0;for(int &i=cur[u];i;i=e[i].next){int v=e[i].v,d=0;if(e[i].w&&level[v]==level[u]+1){d=dfs(v,min(flow,e[i].w));ret+=d;flow-=d;e[i].w-=d;e[i^1].w+=d;if(!flow)break;}}if(!flow)level[u]=0;return ret;
}
void Delete(int u,int v,int &flow)
{int val=0;for(int i=h[v],j=0;i;j=i,i=e[i].next)if(e[i].v==u){j?(e[j].next=e[i].next):(h[v]=e[i].next);break;}for(int i=h[u],j=0;i;j=i,i=e[i].next)if(e[i].v==v){j?(e[j].next=e[i].next):(h[u]=e[i].next);val=e[i].w^1;break;}if(!val)return;--flow;for(int i=h[S];i;i=e[i].next)if(e[i].v==u){e[i].w^=1,e[i^1].w^=1;break;}for(int i=h[T];i;i=e[i].next)if(e[i].v==v){e[i].w^=1,e[i^1].w^=1;break;}if(bfs())flow+=dfs(S,inf);
}
struct Point{double x,y;}p[MAX];
struct Degree{double t;int u,v,opt;}q[MAX];
bool operator<(Degree a,Degree b){return a.t!=b.t?a.t<b.t:a.opt>b.opt;}
double alpha;
bool check(double mid)
{for(int i=S;i<=T;++i)h[i]=0;cnt=2;int tot=0;for(int i=1;i<=n;++i){double dis=sqrt(p[i].x*p[i].x+p[i].y*p[i].y);if(dis>R+mid||dis<R-mid)return false;if(dis+R<=mid)for(int j=1;j<=n;++j)Add(i,j+n,1);else{double ang=atan2(p[i].y,p[i].x);double d=acos((1.0*R*R+dis*dis-mid*mid)/(2*R*dis));double l=ang-d,r=ang+d;while(l<0)l+=2*Pi;while(r<0)r+=2*Pi;int L=l/alpha,R=r/alpha;q[++tot]=(Degree){l-L*alpha,i,L+1,1};q[++tot]=(Degree){r-R*alpha,i,R+1,-1};++L,++R;if(l<=r)for(int j=L+1;j<=R;++j)Add(i,j+n,1);else{for(int j=L+1;j<=n;++j)Add(i,j+n,1);for(int j=1;j<=R;++j)Add(i,j+n,1);}}}for(int i=1;i<=n;++i)Add(S,i,1),Add(i+n,T,1);sort(&q[1],&q[tot+1]);int ans=0;while(bfs())ans+=dfs(S,inf);if(ans==n)return true;for(int i=1;i<=tot;++i)if(q[i].opt==1){Add(q[i].u,q[i].v+n,1);if(bfs())ans+=dfs(S,inf);if(ans==n)return true;}else Delete(q[i].u,q[i].v+n,ans);return false;
}
int main()
{n=read();R=read();alpha=2*Pi/n;S=0;T=n+n+1;for(int i=1;i<=n;++i)p[i].x=read(),p[i].y=read();double l=0,r=400;while(r-l>eps){double mid=(l+r)/2;if(check(mid))r=mid;else l=mid;}printf("%.8lf\n",l);return 0;
}

转载于:https://www.cnblogs.com/cjyyb/p/10420259.html

【BZOJ5316】[JSOI2018]绝地反击(网络流,计算几何,二分)相关推荐

  1. 计算几何(二分) - Crossed Ladders - UVA 10566

    计算几何(二分) - Crossed Ladders - UVA 10566 题意: 如上图,给定三个浮点数x,y,c,计算两个房子之间的间距.如上图,给定三个浮点数x,y,c,计算两个房子之间的间距 ...

  2. (计算几何+二分+网络流)P4048 [JSOI2010]冷冻波

    P4048 [JSOI2010]冷冻波 思路: 首先我们可以假设如果有ansansans分钟的话,巫妖可以攻击⌊anst⌋+1\lfloor\cfrac{ans}{t}\rfloor+1⌊tans​⌋ ...

  3. CF1019D-Large Triangle【计算几何,二分】

    正题 题目链接:https://www.luogu.com.cn/problem/CF1019D 题目大意 给出nnn个点,保证没有三点共线,求是否有三个点围成的三角形面积恰好为SSS. 3≤n≤2× ...

  4. UVA10566 Crossed Ladders(计算几何+二分)

    有两把梯子搭在墙上,给出这两把梯子的长度 x,y,以及他们的交点,交点的高度为 h,求这两个房屋之间的距离 如上图所示,易证红色内有两个三角形相似和绿色内有两个三角形相似 所以有: double x, ...

  5. bzoj3130 [SDOI2013]费用流 结论+二分答案+网络流检验

    这个题看起来很难,但分析一下还是很简单的 Alice的操作是根据Bob来的,而Bob又是知道这个方案的 所以需要考虑对于一个固定的方案,Bob必然怎么加,来确定Alice的方案 然后发现,对于当前割集 ...

  6. UVALive - 3231 Fair Share(最大流+二分)

    题目链接:点击查看 题目大意:给出n个处理器和m个任务,每个任务给出可以运行的两个处理器,只需要其中一个处理器完成即可, 问如何分配处理方案,能使得n个处理器中处理任务最多的处理器所处理的任务最少 题 ...

  7. 网络流之最大流和最小割

    最大流问题 最大流:给定有向图中每条边的最大流量(容量),求从源点到汇点的最大流量. 容量网络: 括号左边代表容量,右边代表流量. 残留网络:流网络中剩余可增加的流量 增广路:满足容量条件的一条流量不 ...

  8. 网络流学习总结和省选专练SCOI2015小凸玩矩阵

    这是四川连着第几个年头考二分套网络流了? 虽然这是一个二分图最大匹配,但是我匈牙利写挂了. 我太弱了. 好了不瞎扯牛逼了,这个题这么搞: 首先题目就告诉你求第k大最小. 首先这就让人瑟瑟发抖....第 ...

  9. 辣鸡HellPix刷yyb网络流题单(orz yyb)

    题目 评价 状态 [USACO4.2]草地排水Drainage Ditches(最大流)  最大流模板 Accepted HDU 3416 Marriage Match IV(最短路,网络流)  最小 ...

  10. 面试高级算法梳理笔记

    作者:尤汐_Jennica 链接: https://www.nowcoder.com/discuss/21253 来源:牛客网 1.1 说明 本篇为<挑战程序设计竞赛(第2版)>读书笔记系 ...

最新文章

  1. 鹅厂2020暑期实习第三次一面
  2. 机器学习实战笔记(Python实现)-04-Logistic回归
  3. 快速实现dNet三层架构项目图解
  4. 结构体交换遇到指针问题和一些记录
  5. 笔记本屏幕出现横条纹_华为再添黑科技,手机一碰笔记本,手机页面就出现在PC屏幕上...
  6. 数字电路课程设计--电子钟实验报告
  7. nideshop小程序商城部署
  8. 大一计算机ppt知识点,大一计算机总复习_图文.ppt
  9. dBm与功率(w)换算关系
  10. 项目管理笔记-第十章 项目沟通管理
  11. 摊销本月技术支持部服务器运维成本会计分录,摊销本月报刊费会计分录_摊销本月报刊费_摊销报刊费的会计分录...
  12. 鹏博士总经理陆榴遭免职 董事称事发突然
  13. 励志照亮人生 编程改变命运
  14. FL Studio 21中文版支持主题随心换,FL Studio 21Mac版新增对苹果M2/1家族芯片原生支持。
  15. 盛迈坤电商:退款率高会影响店铺吗
  16. 【Linux入门学习之】Ubuntu常用软件 速配指南之软件参考
  17. 微金所张继业:规范化运作 回馈投资人
  18. canvas宽高设置
  19. 2020-11-11,单身快乐
  20. Vue父组件传子组件数据中,Vue监听不到数据改变

热门文章

  1. 解决Ubuntu19.04下网易云音乐打不开的问题
  2. ubuntu22.04安装网易云音乐不能打开的问题
  3. python高级练习题:取消列表(比简单更难)【难度:4级】--景越Python编程实例训练营,不同难度Python习题,适合自学Python的新手进阶
  4. 如何隐藏C/C++编译生成的函数符号
  5. 基于粒子群算法的微电网优化调度应用研究(六、总结与展望)
  6. linux磁盘配额分区,Linux磁盘配额
  7. PHPStudy设置局域网访问
  8. mongoDB占内存超大的问题-100MB数据,内存吃到22GB?
  9. Android指南针应用编写
  10. 百度EasyDL图像分类的使用