二分答案
用点对
(x,y)
(
x
,
y
)
表示一个人在
x
x
,另一个在 的状态,当
x
x
和 的距离小于等于二分的答案时,这个状态合法。
两个状态
(x1,y1)
(
x
1
,
y
1
)
和
(x2,y2)
(
x
2
,
y
2
)
直接相连,当且仅当
x1
x
1
和
x2
x
2
之间有边或者
y1
y
1
和
y2
y
2
有边
那么只要用bfs判断一下
(stx,sty)
(
s
t
x
,
s
t
y
)
是否与一个由两个叶子构成的状态相连。
但是两个人是可以任意走动的,也就是在边上也要算
可以把边拆成一个点,一个点和一条边的距离是点到线段的最短距离,边与边的距离是其中一条边的两个端点到另一条边的距离较大值的最小值
然后就跟之前一样判断就好了
考场上点到线段的距离写错了炸成5分…
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#define debug(x) //cerr<<#x<<' '<<x<<endl;
#define fi first
#define se second
using namespace std;
typedef pair<int,int> pii;
const int N=2010;
struct Point{
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
friend Point operator -(Point a,Point b){
return Point(a.x-b.x,a.y-b.y);
}
double len2(){
return x*x+y*y;
}
double len(){
return sqrt(len2());
}
};
struct Line{
Point a,b;
Line(){}
Line(Point _a,Point _b):a(_a),b(_b){}
double len2(){
return (a-b).len2();
}
double len(){
return sqrt(len2());
}
}a[N<<1];
int n,x,y,t,cnt,G[N],vis[N][N];
struct edge{
int t,nx;
}E[N<<1];
inline double dot(Point a,Point b){
return a.x*b.x+a.y*b.y;
}
inline double cross(Point a,Point b){
return a.x*b.y-a.y*b.x;
}
int du[N];
inline void addedge(int x,int y){
E[++cnt].t=y; E[cnt].nx=G[x]; G[x]=cnt; du[x]++;
E[++cnt].t=x; E[cnt].nx=G[y]; G[y]=cnt; du[y]++;
}
inline double dis(Point x,Line y){
double dt=dot(y.a-y.b,x-y.b);
if(dt>0 && dt<y.len2()) return fabs(cross(y.a-y.b,x-y.b)/y.len());
debug((x-y.a).len()); debug((x-y.b).len());
return min((x-y.a).len(),(x-y.b).len());
}
inline double dist(Line x,Line y){
return min(max(dis(x.a,y),dis(x.b,y)),max(dis(y.a,x),dis(y.b,x)));
}
double D[N][N];
queue<pii> Q;
vector<int> sb;
inline bool check(double cc){
for(int i=1;i<=t;i++)
for(int j=1;j<=t;j++)
vis[i][j]=0;
while(!Q.empty()) Q.pop();
Q.push(pii(x,y)); vis[x][y]=vis[y][x]=1;
while(!Q.empty()){
int x=Q.front().fi,y=Q.front().se; Q.pop();
for(int i=G[x];i;i=E[i].nx)
for(int j=G[y];j;j=E[j].nx)
if(!vis[E[i].t][E[j].t] && cc-D[E[i].t][E[j].t]>-1e-6){
vis[E[i].t][E[j].t]=vis[E[j].t][E[i].t]=1;
if(du[E[i].t]==1 && du[E[j].t]==1) return true;
Q.push(pii(E[i].t,E[j].t));
}
for(int i=G[x];i;i=E[i].nx)
if(!vis[E[i].t][y] && cc-D[E[i].t][y]>-1e-6){
vis[E[i].t][y]=vis[y][E[i].t]=1;
if(du[E[i].t]==1 && du[y]==1) return true;
Q.push(pii(E[i].t,y));
}
for(int i=G[y];i;i=E[i].nx)
if(!vis[E[i].t][x] && cc-D[E[i].t][x]>-1e-6){
vis[E[i].t][x]=vis[x][E[i].t]=1;
if(du[E[i].t]==1 && du[x]==1) return true;
Q.push(pii(E[i].t,x));
}
}
return false;
}
int main(){
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
scanf("%d%d%d",&n,&x,&y);
for(int i=1;i<=n;i++){
int cx,cy; scanf("%d%d",&cx,&cy);
sb.push_back(cx); sb.push_back(cy);
a[i]=Line(Point(cx,cy),Point(cx,cy));
}
t=n;
for(int i=1;i<n;i++){
++t; int cx,cy; scanf("%d%d",&cx,&cy);
a[t]=Line(a[cx].a,a[cy].a);
addedge(cx,t); addedge(cy,t);
}
double L=dist(a[x],a[y]),R=0,mid,ret;
for(int i=1;i<=t;i++)
for(int j=1;j<=t;j++)
R=max(R,D[i][j]=dist(a[i],a[j]));
double cur=dist(a[n+2],a[n+6]);
debug(cur);
if(du[x]==1 && du[y]==1) return printf("%.9lf\n",D[x][y]),0;
while(R-L>1e-6)
check(mid=(L+R)/2)?R=mid:L=mid;
printf("%.9lf\n",(L+R)/2);
return 0;
}