BZOJ挂,链自找
很容易发现两个点连线的中垂线就是划分两个点控制区域的直线
那对于每个点处理处它与其他所有点的连线的中垂线,加上边界四条线做半平面交即可知道这个点的控制区域
然后这个点与所有剩下的直线所代表的点连边,跑最短路即可
Code:
#include<bits/stdc++.h>
#define eps 1e-9
#define db double
#define mp make_pair
#define fi first
#define se second
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=2e5+5;
namespace sssp{
int s;
int vis[N<<1],head[N],nxt[N<<1],etot=0;
inline void add(int x,int y){vis[++etot]=y;nxt[etot]=head[x];head[x]=etot;}
int d[N],pt[N];
priority_queue<pair<int,int> >q;
inline void dijkstra(){
memset(d,0x3f,sizeof(d));
memset(pt,0,sizeof(pt));
d[s]=0;q.push(mp(0,s));
while(!q.empty()){
int x=q.top().se;q.pop();pt[x]=1;
for(int i=head[x];i;i=nxt[i]){
int y=vis[i];
if(pt[y]) continue;
if(d[y]>d[x]+1){
d[y]=d[x]+1;
q.push(mp(-d[y],y));
}
}
}
}
}
using namespace sssp;
namespace half_plane_intersection{
bool fcmp(double a,double b){return fabs(b-a)<eps;}
struct point{
db x,y;
point(){}
point(db _x,db _y):x(_x),y(_y){}
friend inline point operator + (const point &a,const point &b){return point(a.x+b.x,a.y+b.y);}
friend inline point operator - (const point &a,const point &b){return point(a.x-b.x,a.y-b.y);}
friend inline point operator * (const point &a,const db &b){return point(a.x*b,a.y*b);}
friend inline db operator * (const point &a,const point &b){return a.x*b.y-a.y*b.x;}
inline point ref(){return point(y,-x);}
}p[N];
struct line{
point x,y;
db ang;
int id;
line(){}
line(point _x,point _y):x(_x),y(_y),ang(atan2(y.y-x.y,y.x-x.x)){}
}l[N];
inline bool lft(line a,point b){return (b-a.x)*(a.y-a.x)+eps>0;}
inline bool cmp(line a,line b){
if(fcmp(a.ang,b.ang)) return lft(a,b.y);
return a.ang<b.ang;
}
point itse(line a,line b){
point bs=a.y-a.x;
db tmp=((b.x-a.x)*bs)/(bs*(b.y-b.x));
return b.x+(b.y-b.x)*tmp;
}
inline point mid(point x,point y){return point((x.x+y.x)/2,(x.y+y.y)/2);}
inline line get(point a,point b){
point c=mid(a,b);
return line(c,c+(b-a).ref());
}
int n,tot;
db ans=0,sum=0;
point st;
int q[N];
inline void hp(int x){
int hd=1,ta=2;
sort(l+1,l+tot+1,cmp);
int pos=1;
for(int i=2;i<=tot;i++) if(fabs(l[i].ang-l[pos].ang)>0) l[++pos]=l[i];
tot=pos;
q[1]=1,q[2]=2;
for(int i=3;i<=tot;i++){
while(hd<ta && lft(l[i],itse(l[q[ta-1]],l[q[ta]]))) --ta;
while(hd<ta && lft(l[i],itse(l[q[hd+1]],l[q[hd]]))) ++hd;
q[++ta]=i;
}
while(hd<ta && lft(l[q[hd]],itse(l[q[ta-1]],l[q[ta]]))) --ta;
for(int i=hd;i<=ta;i++) add(x,l[q[i]].id);
if(ta-hd<2) return;
int f=1;
for(int i=hd;i<=ta;i++) if(lft(l[q[i]],st)) f=0;
if(f) s=x;
}
db xx,yy;
inline void init(int id){
tot=0;
point p1=point(0,0),p2=point(xx,0),p3=point(xx,yy),p4=point(0,yy);
l[++tot]=line(p1,p2),l[++tot]=line(p2,p3),l[++tot]=line(p3,p4),l[++tot]=line(p4,p1);
for(int i=1;i<=4;i++) l[i].id=n+1;
for(int i=1;i<=n;i++) if(i!=id) l[++tot]=get(p[i],p[id]),l[tot].id=i;
}
}
using namespace half_plane_intersection;
int main(){
int t=read();
while(t--){
memset(head,0,sizeof head),etot=0;
n=read();
scanf("%lf%lf%lf%lf",&xx,&yy,&st.x,&st.y);
for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
for(int i=1;i<=n;i++) init(i),hp(i);
dijkstra();
if(d[n+1]==1061109567) cout<<"0"<<"\n";
else cout<<d[n+1]<<"\n";
}
return 0;
}