【BZOJ5316】[JSOI2018]绝地反击(网络流,计算几何,二分)
【BZOJ5316】[JSOI2018]绝地反击(网络流,计算几何,二分)
题面
题解
很明显需要二分一个答案。
那么每个点可以确定的范围就是以当前点为圆心,二分出来的答案为半径画一个圆,和目标的圆的交就是可行的区间。
首先我们不知道正\(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;
}
【BZOJ5316】[JSOI2018]绝地反击(网络流,计算几何,二分)的更多相关文章
- BZOJ5316 : [Jsoi2018]绝地反击
若$R=0$,那么显然答案为离原点最远的点到原点的距离. 否则若所有点都在原点,那么显然答案为$R$. 否则考虑二分答案$mid$,检查$mid$是否可行. 那么每个点根据对应圆交,可以覆盖圆上的一部 ...
- 洛谷P4518 [JSOI2018]绝地反击(计算几何+二分图+退流)
题面 传送门 题解 调了咱一个上午-- 首先考虑二分答案,那么每个点能够到达的范围是一个圆,这个圆与目标圆的交就是可行的区间,这个区间可以用极角来表示 首先,如果我们知道这个正\(n\)边形的转角,也 ...
- 【bzoj1822】[JSOI2010]Frozen Nova 冷冻波 计算几何+二分+网络流最大流
题目描述 WJJ喜欢“魔兽争霸”这个游戏.在游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀死一个小精灵.我们认为,巫妖和小精灵都可以看成是平面上的点. 当巫妖和小精灵之间的直线 ...
- 【BZOJ3993】星际战争(网络流,二分答案)
[BZOJ3993]星际战争(网络流,二分答案) 题面 Description 3333年,在银河系的某星球上,X军团和Y军团正在激烈地作战.在战斗的某一阶段,Y军团一共派遣了N个巨型机器人进攻X军团 ...
- 【BZOJ5251】【八省联考2018】劈配(网络流,二分答案)
[BZOJ5251][八省联考2018]劈配(网络流,二分答案) 题面 洛谷 BZOJ Description 一年一度的综艺节目<中国新代码>又开始了. Zayid从小就梦想成为一名程序 ...
- 【POJ】2318 TOYS ——计算几何+二分
TOYS Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 10281 Accepted: 4924 Description ...
- 洛谷P2402 奶牛隐藏(网络流,二分答案,Floyd)
洛谷题目传送门 了解网络流和dinic算法请点这里(感谢SYCstudio) 题目 题目背景 这本是一个非常简单的问题,然而奶牛们由于下雨已经非常混乱,无法完成这一计算,于是这个任务就交给了你.(奶牛 ...
- 洛谷P4382 [八省联考2018]劈配(网络流,二分答案)
洛谷题目传送门 说不定比官方sol里的某理论最优算法还优秀一点? 所以\(n,m\)说不定可以出到\(1000\)? 无所谓啦,反正是个得分题.Orz良心出题人,暴力有70分2333 思路分析 正解的 ...
- LGP4518[JSOI2018]绝地反击
题解: 只要确定了每艘飞船的就位位置,就可以用二分+网络流求得答案: 定义偏转角度$a$为离$x$正半轴逆时针最近的边的弧度,$a \in [0,\frac{2\pi}{n})$ 二分一个值,对于一个 ...
随机推荐
- IOS 开发之-- textfield和textview,return键的改变,点击return键
IOS 开发之-- textfield和textview,return键的改变,点击return键 一,textfield的return键改变 方案1.改变键盘右下角的换行(enter)键为完成键,后 ...
- shell脚本--CGI获取请求数据(GET / POST)
Case 1: 获取地址栏传递的参数(即通过GET方式) CGI的环境变量中有个QUERY_STRING,可以获取地址栏传递的参数,该参数可以是手动加上的,也可以是通过表单的get方式提交的,比如下面 ...
- Java遍历HashMap并修改(remove)(转载)
遍历HashMap的方法有多种,比如通过获取map的keySet, entrySet, iterator之后,都可以实现遍历,然而如果在遍历过程中对map进行读取之外的操作则需要注意使用的遍历方式和操 ...
- mysql的主从复制
一.主从复制简介 二.主从复制原理 四.主从复制基本故障处理 五.延时从库 六.半同步复制 七.过滤复制 四.主从复制基本故障处理 SQL 线程为NO 一般情况下,因为主库一开始本来就有一些存在的库, ...
- Linux基础学习笔记1
MBR分区 主分区: 1-4,一块硬盘最多四个主分区,对主机必须有,主区可以格式化ntfs,存数据: 扩展分区:1-4,一块硬盘最多一个扩展分区,可以没有扩展分区,划分更小的单元,即逻辑分区: 逻辑分 ...
- ssh 登陆服务器原理
这里分两种情况,这两种情况都涉及到公钥加密的概念. 由于公钥加密概念作为基础就不在本文进行讨论了. 使用ssh对远程服务器进行密码登录发生了什么: 客户端通过ssh连接服务器 1. 首先服务器把自己的 ...
- asyncio并发编程
一. 事件循环 1.注: 实现搭配:事件循环+回调(驱动生成器[协程])+epoll(IO多路复用),asyncio是Python用于解决异步编程的一整套解决方案: 基于asynico:tornado ...
- 使用ultraiso制作启动盘安装windows操作系统
1. 使用ultraiso制作u盘启动盘 在电脑上安装ultraiso: 启动ultraiso,文件->打开->选中iso镜像文件 菜单栏->启动->写入硬盘映像 a. 便捷启 ...
- mybatis generator的maven插件,找不到properties的配置文件错误的解决
第一次运行的时候,maven插件是正确运行了的 但后面对 maven 的 build节点做了一点修改,就开始报错,找不到 properties标签指定的的数据库连接配置文件了 修改部分如下: 这个操作 ...
- shiro使用ajax登陆实现,success但页面无法跳转的问题
首先:简述一下登陆的后台流程 页面提交——>对应controller中的方法——>对应Realm认证——>controller返回 json 这样,无论成功与否,都有返回值,可以用 ...