Problem:
Problem E:
Hide-and-seek
Hide-and-seek
is a children’s game. Players hide here and there, and one player called
it
tries to find all
the other players.
Now you played
it
and found all the players, so it’s turn to hide from
it
. Since you have got tired of
running around for finding players, you don’t want to play
it
again. So you are going to hide yourself at
the place as far as possible from
it
. But where is that?
Your task is to find the place and calculate the maximum possible distance from
it
to the place to hide.
Input
The input contains a number of test cases.
The first line of each test case contains a positive integer
N
(
N
≤ 1000). The following N lines give
the map where hide-and-seek is played. The map consists of
N corridors
. Each line contains four real
numbers
x
1
,
y
1
,
x
2
, and
y
2
, where (
x
1
,
y
1
) and (
x
2
,
y
2
) indicate the two end points of the corridor. All
corridors are straight, and their widths are negligible. After these
N
lines, there is a line containing two
real numbers
sx
and
sy
, indicating the position of
it
. You can hide at an arbitrary place of any corridor,
and
it
always walks along corridors. Numbers in the same line are separated by a single space.
It is guaranteed that
its
starting position (
sx
,
sy
) is located on some corridor and linked to all corridors
directly or indirectly.
The end of the input is indicated by a line containing a single zero.
Output
For each test case, output a line containing the distance along the corridors from ‘it”s starting position
to the farthest position. The value may contain an error less than or equal to 0.001. You may print any
number of digits below the decimal point.
Sample Input
2
0 0 3 3
0 4 3 1
1 1
0
Output for the Sample Input
4.243

Submitted solutions:

code_snippet: #include <iostream>
#include <iomanip>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
#include <array>
#include <map>
#include <utility>
#include <queue>
using namespace std;
const double EPS = 1e-8;
const double INF = 1e12;
const double PI = acos(-1);
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : array<P, 2>{
    L(const P& a, const P& b){ at(0)=a; at(1)=b; }
    L(){}
};

namespace std{
    bool operator < (const P& a, const P& b){
        return !EQ(a.X,b.X) ? a.X<b.X : a.Y+EPS<b.Y;
    }
    bool operator == (const P& a, const P& b){
        return abs(a-b) < EPS;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1; //ccw
    if(cross(b,c) < -EPS) return -1; //cw
    if(dot(b,c) < -EPS) return +2; //c-a-b
    if(abs(c)-abs(b) > EPS) return -2; //a-b-c
    return 0; //a-c-b
}

bool intersectSS(const L& a, const L& b){
    return ( ccw(a[0],a[1],b[0]) *ccw(a[0],a[1],b[1]) <= 0 ) &&
        ( ccw(b[0],b[1],a[0]) *ccw(b[0],b[1],a[1]) <= 0 );
}
bool intersectSP(const L& s, const P &p){
    return abs(cross(s[0]-p, s[1]-p))<EPS  && dot(s[0]-p, s[1]-p)<EPS;
}

bool isParallel(const P &a, const P &b){
    return abs(cross(a,b)) < EPS;
}
bool isParallel(const L &a, const L &b){
    return isParallel(a[1]-a[0], b[1]-b[0]);
}

P crosspointLL(const L &l, const L &m) {
  double A = cross(l[1]-l[0], m[1]-m[0]);
  double B = cross(l[1]-l[0], l[1]-m[0]);
  return m[0] + B/A *(m[1]-m[0]);
}

pair<vector<vector<pair<int, double> > >, VP> arrangementEX(const vector<L> &l, const P &sp){
    vector<VP> cp(l.size());
    VP plist;
    plist.push_back(sp);
    for(int i=0; i<(int)l.size(); i++){
        for(int j=i+1; j<(int)l.size(); j++){
            if(!isParallel(l[i], l[j]) && intersectSS(l[i], l[j])){
                P cpij = crosspointLL(l[i], l[j]);
                cp[i].push_back(cpij);
                cp[j].push_back(cpij);
                plist.push_back(cpij);
            }
        }
        if(intersectSP(l[i], sp)){
            cp[i].push_back(sp);
        }
        cp[i].push_back(l[i][0]);
        cp[i].push_back(l[i][1]);
        plist.push_back(l[i][0]);
        plist.push_back(l[i][1]);
        sort(cp[i].begin(), cp[i].end());
        cp[i].erase(unique(cp[i].begin(), cp[i].end()), cp[i].end());
        for(int j=cp[i].size()-2; j>=0; j--){
            P mid = (cp[i][j] +cp[i][j+1]) /2.0;
            cp[i].push_back(mid);
            plist.push_back(mid);
        }
        sort(cp[i].begin(), cp[i].end());
        cp[i].erase(unique(cp[i].begin(), cp[i].end()), cp[i].end());
    }
    sort(plist.begin(), plist.end());
    plist.erase(unique(plist.begin(), plist.end()), plist.end());

    int n = plist.size();
    map<P, int> conv;
    for(int i=0; i<n; i++){
        conv[plist[i]] = i;
    }
    vector<vector<pair<int, double> > > adj(n);
    for(int i=0; i<(int)cp.size(); i++){
        for(int j=0; j<(int)cp[i].size()-1; j++){
            int jidx = conv[cp[i][j]];
            int jp1idx = conv[cp[i][j+1]];
            double dist = abs(cp[i][j] -cp[i][j+1]);
            adj[jidx].emplace_back(jp1idx, dist);
            adj[jp1idx].emplace_back(jidx, dist);
        }
    }
    for(int i=0; i<n; i++){
        sort(adj[i].begin(), adj[i].end());
        adj[i].erase(unique(adj[i].begin(), adj[i].end()), adj[i].end());
    }
    return make_pair(adj, plist);
}

int main(){
    while(1){
        int n;
        cin >> n;
        if(n == 0) break;

        vector<L> l(n);
        for(int i=0; i<n; i++){
            double xs,ys,xt,yt;
            cin >> xs >> ys >> xt >> yt;
            l[i] = L(P(xs, ys), P(xt, yt));
        }
        double sx,sy;
        cin >> sx >> sy;
        P s(sx, sy);

        pair<vector<vector<pair<int, double> > >, VP> ret = arrangementEX(l, s);
        vector<vector<pair<int, double> > > &adj = ret.first;
        VP &plist = ret.second;
        int m = plist.size();
        int sidx = lower_bound(plist.begin(), plist.end(), s) -plist.begin();

        priority_queue<pair<double, int> > wait;
        wait.push(make_pair(0, sidx));
        vector<double> mincost(m, INF);
        mincost[sidx] = 0;
        while(!wait.empty()){
            double dist = -wait.top().first;
            int pos = wait.top().second;
            wait.pop();
            if(dist > mincost[pos]) continue;

            for(pair<int, double> next: adj[pos]){
                int npos = next.first;
                double ndist = dist +next.second;
                if(ndist +EPS < mincost[npos]){
                    mincost[npos] = ndist;
                    wait.push(make_pair(-ndist, npos));
                }
            }
        }

        cout << fixed << setprecision(10);
        cout << *max_element(mincost.begin(), mincost.end()) << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 1140
memory_kb: 33364
final_rank: 13

code_snippet: #include<bits/stdc++.h>
#define MAX 100000
#define inf 1<<29
#define linf 1e18
#define eps (1e-8)
#define mod 1000000007
#define pi M_PI
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<double,int> pdi;
typedef pair<int,double> pid;
typedef vector<int> vi;
typedef vector<pii> vpi;
const int dx[8]={1,0,-1,0,1,1,-1,-1};
const int dy[8]={0,1,0,-1,1,-1,1,-1};

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):x(x),y(y){}
 
  Point operator+(Point p){ return Point(x+p.x,y+p.y);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y);}
  Point operator*(double k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ return (x!=p.x ? x-p.x<-eps : y-p.y<-eps);}
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}
 
  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;
 
class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;
 
double norm(Vector a){ return (a.x*a.x+a.y*a.y);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
double cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}
 
int ccw(Point p0,Point p1,Point p2){
  Vector a=p1-p0;
  Vector b=p2-p0;
  if(cross(a,b)>eps)return 1;
  if(cross(a,b)<-eps)return -1;
  if(dot(a,b)<-eps)return 2;
  if(a.norm()<b.norm())return -2;
  return 0;
}
 
bool intersect(Point p1,Point p2,Point p3,Point p4){
  return (ccw(p1,p2,p3)*ccw(p1,p2,p4)<=0 &&
          ccw(p3,p4,p1)*ccw(p3,p4,p2)<=0);
}
 
bool intersect(Segment s1,Segment s2){
  return intersect(s1.p1,s1.p2,s2.p1,s2.p2);
}
 
Point getCrossPointLL(Line a,Line b){
  double A=cross(a.p2-a.p1,b.p2-b.p1);
  double B=cross(a.p2-a.p1,a.p2-b.p1);
  if(abs(A)<eps || abs(B)<eps)return b.p1;
  return b.p1+(b.p2-b.p1)*(B/A);
}

typedef vector<vector<int> > Graph;
 
Graph SegmentArrangement(vector<Segment> v,vector<Point> &ps){
  for(int i=0;i<v.size();i++){
    ps.push_back(v[i].p1);
    ps.push_back(v[i].p2);
    for(int j=i+1;j<v.size();j++){
      if(intersect(v[i],v[j]))ps.push_back(getCrossPointLL(v[i],v[j]));
    }
  }
  sort(ps.begin(),ps.end());
  ps.erase(unique(ps.begin(),ps.end()),ps.end());
  Graph g(ps.size());
  for(int i=0;i<v.size();i++){
    vector<pair<double,int> > list;
    for(int j=0;j<ps.size();j++)
      if(ccw(v[i].p1,v[i].p2,ps[j])==0)
        list.push_back(mp(norm(v[i].p1-ps[j]),j));
    sort(list.begin(),list.end());
    for(int j=0;j<list.size()-1;j++){
      int a=list[j].s,b=list[j+1].s;
      g[a].push_back(b);
      g[b].push_back(a);
    }
  }
  return g;
}

Graph g;
vector<Point> vp;
int n;
vector<Segment> vs;
Point s;
int start;
double d[MAX];

void init(){
  vs.clear();
  vp.clear();
  g.clear();
}

void dijkstra(){
  FOR(i,0,MAX)d[i]=linf;
  priority_queue<pdi,vector<pdi>,greater<pdi> > pq;
  pq.push(mp(0.0,start));
  d[start]=0.0;

  while(pq.size()){
    pdi u=pq.top();
    pq.pop();

    if(d[u.s]-u.f<-eps)continue;

    FOR(i,0,g[u.s].size()){
      int next=g[u.s][i];
      double cost=abs(vp[u.s]-vp[next]);
      if(u.f+cost-d[next]<-eps){
        d[next]=u.f+cost;
        pq.push(mp(d[next],next));
      }
    }
  }
}

double solve(){
  double res=0;
  vp.pb(s);
  g=SegmentArrangement(vs,vp);
  FOR(i,0,vp.size())if(s==vp[i])start=i;
  dijkstra();
  FOR(i,0,vp.size()){
    if(d[i]!=linf){
      res=max(res,d[i]);
      FOR(j,0,g[i].size()){
        int next=g[i][j];
        double cost=abs(vp[next]-vp[i]);
        res=max(res,min(d[i],d[next])+(cost-abs(d[i]-d[next]))/2.0);
      }
    }
  }
  return res;
}

int main()
{
  while(1){
    cin>>n;
    if(n==0)break;
    init();
    FOR(i,0,n){
      double a,b,c,d;
      cin>>a>>b>>c>>d;
      vs.pb(Segment(Point(a,b),Point(c,d)));
    }
    cin>>s.x>>s.y;
    pd(solve());
  }
  return 0;
}
accuracy: 1
time_ms: 1360
memory_kb: 9472
final_rank: 4

code_snippet: #include<bits/stdc++.h>
#define MAX 100000
#define inf 1<<29
#define linf 1e18
#define eps (1e-8)
#define mod 1000000007
#define pi M_PI
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<double,int> pdi;
typedef pair<int,double> pid;
typedef vector<int> vi;
typedef vector<pii> vpi;
const int dx[8]={1,0,-1,0,1,1,-1,-1};
const int dy[8]={0,1,0,-1,1,-1,1,-1};

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):x(x),y(y){}
 
  Point operator+(Point p){ return Point(x+p.x,y+p.y);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y);}
  Point operator*(double k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ return (x!=p.x ? x-p.x<-eps : y-p.y<-eps);}
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}
 
  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;
 
class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;
 
double norm(Vector a){ return (a.x*a.x+a.y*a.y);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
double cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}
 
bool isParallel(Segment s,Segment t){
  return equals(cross(s.p1-s.p2,t.p1-t.p2),0.0);
}
 
int ccw(Point p0,Point p1,Point p2){
  Vector a=p1-p0;
  Vector b=p2-p0;
  if(cross(a,b)>eps)return 1;
  if(cross(a,b)<-eps)return -1;
  if(dot(a,b)<-eps)return 2;
  if(a.norm()<b.norm())return -2;
  return 0;
}
 
bool intersect(Point p1,Point p2,Point p3,Point p4){
  return (ccw(p1,p2,p3)*ccw(p1,p2,p4)<=0 &&
          ccw(p3,p4,p1)*ccw(p3,p4,p2)<=0);
}
 
bool intersect(Segment s1,Segment s2){
  return intersect(s1.p1,s1.p2,s2.p1,s2.p2);
}
 
Point getCrossPointLL(Line a,Line b){
  double A=cross(a.p2-a.p1,b.p2-b.p1);
  double B=cross(a.p2-a.p1,a.p2-b.p1);
  if(abs(A)<eps || abs(B)<eps)return b.p1;
  return b.p1+(b.p2-b.p1)*(B/A);
}

typedef vector<vector<int> > Graph;
 
Graph SegmentArrangement(vector<Segment> v,vector<Point> &ps){
  for(int i=0;i<v.size();i++){
    ps.push_back(v[i].p1);
    ps.push_back(v[i].p2);
    for(int j=i+1;j<v.size();j++){
      if(intersect(v[i],v[j]))ps.push_back(getCrossPointLL(v[i],v[j]));
    }
  }
  sort(ps.begin(),ps.end());
  ps.erase(unique(ps.begin(),ps.end()),ps.end());
  Graph g(ps.size());
  for(int i=0;i<v.size();i++){
    vector<pair<double,int> > list;
    for(int j=0;j<ps.size();j++)
      if(ccw(v[i].p1,v[i].p2,ps[j])==0)
        list.push_back(mp(norm(v[i].p1-ps[j]),j));
    sort(list.begin(),list.end());
    for(int j=0;j<list.size()-1;j++){
      int a=list[j].s,b=list[j+1].s;
      g[a].push_back(b);
      g[b].push_back(a);
    }
  }
  return g;
}

Graph g;
vector<Point> vp;
int n;
vector<Segment> vs;
Point s;
int start;
double d[MAX];

void init(){
  vs.clear();
  vp.clear();
  g.clear();
}

void dijkstra(){
  FOR(i,0,MAX)d[i]=linf;
  priority_queue<pdi,vector<pdi>,greater<pdi> > pq;
  pq.push(mp(0.0,start));
  d[start]=0.0;

  while(pq.size()){
    pdi u=pq.top();
    pq.pop();

    if(d[u.s]-u.f<-eps)continue;

    FOR(i,0,g[u.s].size()){
      int next=g[u.s][i];
      double cost=abs(vp[u.s]-vp[next]);
      if(u.f+cost-d[next]<-eps){
        d[next]=u.f+cost;
        pq.push(mp(d[next],next));
      }
    }
  }
}

double solve(){
  double res=0;
  vp.pb(s);
  g=SegmentArrangement(vs,vp);
  FOR(i,0,vp.size())if(s==vp[i])start=i;
  dijkstra();
  FOR(i,0,vp.size()){
    if(d[i]!=linf){
      res=max(res,d[i]);
      FOR(j,0,g[i].size()){
        int next=g[i][j];
        double cost=abs(vp[next]-vp[i]);
        res=max(res,min(d[i],d[next])+(cost-abs(d[i]-d[next]))/2.0);
      }
    }
  }
  return res;
}

int main()
{
  while(cin>>n && n){
    init();
    FOR(i,0,n){
      double a,b,c,d;
      cin>>a>>b>>c>>d;
      vs.pb(Segment(Point(a,b),Point(c,d)));
    }
    cin>>s.x>>s.y;
    pd(solve());
  }
  return 0;
}
accuracy: 1
time_ms: 1360
memory_kb: 9452
final_rank: 3

code_snippet: #include<bits/stdc++.h>
#define MAX 100000
#define inf 1<<29
#define linf 1e18
#define eps (1e-8)
#define mod 1000000007
#define pi M_PI
#define f first
#define s second
#define mp make_pair
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define pd(a) printf("%.10f\n",(double)(a))
#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define RFOR(i,a,b) for(int i=(a)-1;(b)<=i;i--)
#define equals(a,b) (fabs((a)-(b))<eps)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<double,int> pdi;
typedef pair<int,double> pid;
typedef vector<int> vi;
typedef vector<pii> vpi;
const int dx[8]={1,0,-1,0,1,1,-1,-1};
const int dy[8]={0,1,0,-1,1,-1,1,-1};

class Point{
public:
  double x,y;
  Point(double x=0,double y=0):x(x),y(y){}
 
  Point operator+(Point p){ return Point(x+p.x,y+p.y);}
  Point operator-(Point p){ return Point(x-p.x,y-p.y);}
  Point operator*(double k){ return Point(x*k,y*k);}
  Point operator/(double k){ return Point(x/k,y/k);}
  bool operator<(Point p)const{ return (x!=p.x ? x<p.x : y<p.y);}
  bool operator==(Point p)const{ return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}
 
  double abs(){ return sqrt(norm());}
  double norm(){ return (x*x+y*y);}
};
typedef Point Vector;
typedef vector<Point> Polygon;
 
class Segment{
public:
  Point p1,p2;
  Segment(Point p1=Point(),Point p2=Point()):p1(p1),p2(p2){}
};
typedef Segment Line;
 
double norm(Vector a){ return (a.x*a.x+a.y*a.y);}
double abs(Vector a){ return sqrt(norm(a));}
double dot(Vector a,Vector b){ return (a.x*b.x+a.y*b.y);}
double cross(Vector a,Vector b){ return (a.x*b.y-a.y*b.x);}
 
bool isParallel(Segment s,Segment t){
  return equals(cross(s.p1-s.p2,t.p1-t.p2),0.0);
}
 
int ccw(Point p0,Point p1,Point p2){
  Vector a=p1-p0;
  Vector b=p2-p0;
  if(cross(a,b)>eps)return 1;
  if(cross(a,b)<-eps)return -1;
  if(dot(a,b)<-eps)return 2;
  if(a.norm()<b.norm())return -2;
  return 0;
}
 
bool intersect(Point p1,Point p2,Point p3,Point p4){
  return (ccw(p1,p2,p3)*ccw(p1,p2,p4)<=0 &&
          ccw(p3,p4,p1)*ccw(p3,p4,p2)<=0);
}
 
bool intersect(Segment s1,Segment s2){
  return intersect(s1.p1,s1.p2,s2.p1,s2.p2);
}
 
Point getCrossPointLL(Line a,Line b){
  double A=cross(a.p2-a.p1,b.p2-b.p1);
  double B=cross(a.p2-a.p1,a.p2-b.p1);
  if(abs(A)<eps || abs(B)<eps)return b.p1;
  return b.p1+(b.p2-b.p1)*(B/A);
}
 
bool merge_if_able(Segment &s,Segment t) {
  if(!isParallel(s,t))return false;
  if(ccw(s.p1,t.p1,s.p2)==1 ||
     ccw(s.p1,t.p1,s.p2)==-1)return false;
  if(ccw(s.p1,s.p2,t.p1)==-2 ||
     ccw(t.p1,t.p2,s.p1)==-2)return false;
  s=Segment(min(s.p1,t.p1),max(s.p2,t.p2));
  return true;
}
 
void merge(vector<Segment>& v) {
  for(int i=0;i<v.size();i++){
    if(v[i].p2<v[i].p1)swap(v[i].p2,v[i].p1);
  }
  for(int i=0;i<v.size();i++)
    for(int j=i+1;j<v.size();j++)
      if(merge_if_able(v[i],v[j]))
        v[j--]=v.back(),v.pop_back();
}
 
typedef vector<vector<int> > Graph;
 
Graph SegmentArrangement(vector<Segment> v,vector<Point> &ps){
  for(int i=0;i<v.size();i++){
    ps.push_back(v[i].p1);
    ps.push_back(v[i].p2);
    for(int j=i+1;j<v.size();j++){
      if(intersect(v[i],v[j]))ps.push_back(getCrossPointLL(v[i],v[j]));
    }
  }
  //sort(ps.begin(),ps.end());
  //ps.erase(unique(ps.begin(),ps.end()),ps.end());
  Graph g(ps.size());
  for(int i=0;i<v.size();i++){
    vector<pair<double,int> > list;
    for(int j=0;j<ps.size();j++)
      if(ccw(v[i].p1,v[i].p2,ps[j])==0)
        list.push_back(mp(norm(v[i].p1-ps[j]),j));
    sort(list.begin(),list.end());
    for(int j=0;j<list.size()-1;j++){
      int a=list[j].s,b=list[j+1].s;
      g[a].push_back(b);
      g[b].push_back(a);
    }
  }
  return g;
}

Graph g;
vector<Point> vp;
int n;
vector<Segment> vs;
Point s;
int start;
double d[MAX];

void init(){
  vs.clear();
  vp.clear();
  g.clear();
}

void dijkstra(){
  FOR(i,0,MAX)d[i]=linf;
  priority_queue<pdi,vector<pdi>,greater<pdi> > pq;
  pq.push(mp(0.0,start));
  d[start]=0.0;

  while(pq.size()){
    pdi u=pq.top();
    pq.pop();

    if(d[u.s]-u.f<-eps)continue;

    FOR(i,0,g[u.s].size()){
      int next=g[u.s][i];
      double cost=abs(vp[u.s]-vp[next]);
      if(u.f+cost-d[next]<-eps){
        d[next]=u.f+cost;
        pq.push(mp(d[next],next));
      }
    }
  }
}

double solve(){
  double res=0;
  merge(vs);
  vp.pb(s);
  g=SegmentArrangement(vs,vp);
  FOR(i,0,vp.size())if(s==vp[i])start=i;
  dijkstra();
  FOR(i,0,vp.size()){
    if(d[i]!=linf){
      res=max(res,d[i]);
      FOR(j,0,g[i].size()){
        int next=g[i][j];
        double cost=abs(vp[next]-vp[i]);
        res=max(res,min(d[i],d[next])+(cost-abs(d[i]-d[next]))/2.0);
      }
    }
  }
  return res;
}

int main()
{
  while(cin>>n && n){
    init();
    FOR(i,0,n){
      double a,b,c,d;
      cin>>a>>b>>c>>d;
      vs.pb(Segment(Point(a,b),Point(c,d)));
    }
    cin>>s.x>>s.y;
    pd(solve());
  }
  return 0;
}
accuracy: 1
time_ms: 1320
memory_kb: 9516
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <map>
#include <queue>
#include <set>
#include <functional>
#include <ctime>
#include <numeric>

using namespace std;

#define fst first
#define snd second
#define all(c) ((c).begin()), ((c).end())
#define TEST(x,a) { auto y=(x); if (sign(y-a)) { cout << "line " << __LINE__  << #x << " = " << y << " != " << a << endl; exit(-1); } }
double urand() { return rand() / (1.0 + RAND_MAX); }

const double PI = acos(-1.0);

// implementation note: use EPS only this function
// usage note: check sign(x) < 0, sign(x) > 0, or sign(x) == 0
// notice: should be normalize to O(1)
const double EPS = 1e-8;
int sign(double x) {
  if (x < -EPS) return -1;
  if (x > +EPS) return +1;
  return 0;
}
struct point {
  typedef double T;
  T x, y; 
  point &operator+=(point p) { x += p.x; y += p.y; return *this; }
  point &operator-=(point p) { x -= p.x; y -= p.y; return *this; }
  point &operator*=(T a)     { x *= a;   y *= a;   return *this; }
  point &operator/=(T a)     { return *this *= (1.0/a); }
  point operator-() const    { return {-x, -y}; }
  bool operator==(point p) const { return !sign(x-p.x) && !sign(y-p.y); }
  bool operator<(point p) const { return x!=p.x ? x<p.x : y<p.y; } // for sort
};
point operator+(point p, point q) { return p += q; }
point operator-(point p, point q) { return p -= q; }
point operator*(point::T a, point p) { return p *= a; }
point operator*(point p, point::T a) { return p *= a; }
point operator/(point p, point::T a) { return p /= a; }
point::T dot(point p, point q) { return p.x*q.x+p.y*q.y; }
point::T cross(point p, point q) { return p.x*q.y-p.y*q.x; } // left turn > 0
point::T norm2(point p) { return dot(p,p); }
point orth(point p) { return {-p.y, p.x}; }
point::T norm(point p) { return sqrt(dot(p,p)); }

struct segment { point p, q; };

vector<point> intersect(segment s, segment t) {
  auto a = cross(s.q - s.p, t.q - t.p);
  auto b = cross(t.p - s.p, t.q - t.p); 
  auto c = cross(s.q - s.p, s.p - t.p);
  if (a < 0) { a = -a; b = -b; c = -c; }
  if (sign(b) < 0 || sign(a-b) < 0 ||
      sign(c) < 0 || sign(a-c) < 0) return {};      // disjoint
  if (sign(a) != 0) return {s.p + b/a*(s.q - s.p)}; // properly crossing
  vector<point> ps;                                 // same line
  auto insert_if_possible = [&](point p) {
    for (auto q: ps) if (sign(dot(p-q, p-q)) == 0) return;
    ps.push_back(p);
  };
  if (sign(dot(s.p-t.p, s.q-t.p)) <= 0) insert_if_possible(t.p);
  if (sign(dot(s.p-t.q, s.q-t.q)) <= 0) insert_if_possible(t.q);
  if (sign(dot(t.p-s.p, t.q-s.p)) <= 0) insert_if_possible(s.p);
  if (sign(dot(t.p-s.q, t.q-s.q)) <= 0) insert_if_possible(s.q);
  return ps;
}

struct arrangement {
  struct edge {
    int src, dst;
    point::T weight;
  };
  int n;
  vector<point> ps; // ps[id[p]] = p, id[ps[k]] = k
  map<point,int> id; 
  vector<vector<edge>> adj;

  arrangement(vector<segment> ss) : n(0) {
    vector<vector<pair<point::T, int>>> group(ss.size());
    auto append = [&](int i, point p) {
      if (!id.count(p)) { id[p] = n++; ps.push_back(p); }
      group[i].push_back({norm(ss[i].p - p), id[p]});
    };
    for (int i = 0; i < ss.size(); ++i) {
      append(i, ss[i].p);
      append(i, ss[i].q);
      for (int j = 0; j < i; ++j) {
        auto qs = intersect(ss[i], ss[j]);
        if (qs.size() == 1) {
          append(i, qs[0]);
          append(j, qs[0]);
        }
      }
    }
    adj.resize(n);
    for (auto &vs: group) {
      sort(all(vs));
      for (int i = 0; i+1 < vs.size(); ++i) {
        auto u = vs[i].snd, v = vs[i+1].snd;
        if (u == v) continue;
        auto len = vs[i+1].fst - vs[i].fst;
        adj[u].push_back({u, v, len});
        adj[v].push_back({v, u, len});
      }
    }
  }
  void shortest_path(point sp) {
    int s = id[sp];
    vector<point::T> dist(n, 1.0/0.0);
    vector<int> prev(n, -1);
    typedef pair<point::T, int> node;
    priority_queue<node, vector<node>, greater<node>> Q;
    Q.push(node(dist[s] = 0, s));
    while (!Q.empty()) {
      node z = Q.top(); Q.pop();
      if (dist[z.snd] <= z.fst) {
        for (auto e: adj[z.snd]) {
          if (dist[e.dst] > dist[e.src] + e.weight) {
            dist[e.dst] = dist[e.src] + e.weight;
            prev[e.dst] = e.src;
            Q.push({dist[e.dst], e.dst});
          }
        }
      }
    }
    point::T ans = 0;
    for (int u = 0; u < n; ++u) {
      for (edge e: adj[u]) {
        point::T s = (dist[e.dst] - dist[e.src] + e.weight)/2;
        ans = max(ans, dist[e.src] + s);
      }
    }
    printf("%.12lf\n", ans);
  }
};


int main() {
  for (int m; ~scanf("%d", &m) && m != 0; ) {
    vector<segment> ss;
    for (int i = 0; i < m; ++i) {
      segment s;
      scanf("%lf %lf %lf %lf", &s.p.x, &s.p.y, &s.q.x, &s.q.y);
      ss.push_back(s);
    }
    point p; 
    scanf("%lf %lf", &p.x, &p.y);
    ss.push_back({p, p});
    arrangement arr(ss);
    arr.shortest_path(p);
  }
}
accuracy: 1
time_ms: 340
memory_kb: 11888
final_rank: 1

code_snippet: #include <cassert>// c
#include <iostream>// io
#include <iomanip>
#include <fstream>
#include <sstream>
#include <vector>// container
#include <map>
#include <set>
#include <queue>
#include <bitset>
#include <stack>
#include <algorithm>// other
#include <utility>
#include <complex>
#include <numeric>
#include <functional>
#include <random>
#include <regex>
using namespace std;
typedef long long ll;

#define ALL(c) (c).begin(),(c).end()
#define FOR(i,l,r) for(int i=(int)l;i<(int)r;++i)
#define REP(i,n) FOR(i,0,n)
#define FORr(i,l,r) for(int i=(int)r-1;i>=(int)l;--i)
#define REPr(i,n) FORr(i,0,n)
#define EACH(i,c) for(__typeof((c).begin()) i=(c).begin(); i!=(c).end(); ++i)
#define IN(l,v,r) ((l)<=(v) && (v)<(r))
#define UNIQUE(v) v.erase(unique(ALL(v)),v.end())

// must template
typedef long double D;
const D INF = 1e20,EPS = 1e-10;

int sig(D a,D b=0){return a<b-EPS?-1:a>b+EPS?1:0;}
template<typename T> bool eq(const T& a,const T& b){return sig(abs(a-b))==0;}


typedef D Cost;Cost CINF=1e20;
struct Edge{
	int from,to;Cost cost;
	Edge(int from,int to,Cost cost) : from(from),to(to),cost(cost) {};
	bool operator<(Edge r) const{return cost<r.cost;}
	bool operator>(Edge r) const{return cost>r.cost;}
};
typedef vector<vector<Edge> >  Graph;
typedef complex<D> P;
#define X real()
#define Y imag()

bool compX (const P& a,const P& b){return !eq(a.X,b.X)?sig(a.X,b.X)<0:sig(a.Y,b.Y)<0;}
istream& operator >> (istream& is,P& p){D x,y;is >> x >> y;p=P(x,y);return is;}

namespace std{
	bool operator <  (const P& a,const P& b){return compX(a,b);}
  	bool operator == (const P& a,const P& b){return eq(a,b);}
};

// a×b
D cross(const P& a,const P& b){return imag(conj(a)*b);}
// a・b
D dot(const P& a,const P& b) {return real(conj(a)*b);}

int ccw(const P& a,P b,P c){
	b -= a; c -= a;
	if (sig(cross(b,c)) > 0)   return +1;       // counter clockwise
	if (sig(cross(b,c)) < 0)   return -1;       // clockwise
	if (sig(dot(b,c)) < 0)     return +2;       // c--a--b on line
	if (sig(norm(b),norm(c))<0) return -2;       // a--b--c on line
	return 0; //a--c--b on line or c==a or c==b
}

//直線・線分
struct L : public vector<P> {
	P vec() const {return this->at(1)-this->at(0);}
	L(const P &a, const P &b){push_back(a); push_back(b);}
	L(){push_back(P(0,0));push_back(P(0,0));}
};
istream& operator >> (istream& is,L& l){is >> l[0] >> l[1];return is;}

bool isIntersectLL(const L &l, const L &m) {
 	return sig(cross(l.vec(), m.vec()))!=0 || // non-parallel
	sig(cross(l.vec(), m[0]-l[0])) == 0;   // same line
}
bool isIntersectLS(const L &l, const L &s) {
	return sig(cross(l.vec(), s[0]-l[0])*       // s[0] is left of l
		cross(l.vec(), s[1]-l[0]))<=0; // s[1] is right of l
}
bool isIntersectLP(const L &l, const P &p) {return sig(cross(l[1]-p, l[0]-p))==0;}

// verified by ACAC003 B
// http://judge.u-aizu.ac.jp/onlinejudge/creview.jsp?rid=899178&cid=ACAC003
bool isIntersectSS(const L &s, const L &t) {
	return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
		ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}
bool isIntersectSP(const L &s, const P &p) {
	return sig(abs(s[0]-p)+abs(s[1]-p),abs(s[1]-s[0])) <=0; // triangle inequality
}
P crosspoint(const L &l, const L &m) {
	D A = cross(l.vec(), m.vec());
	D B = cross(l.vec(), l[1] - m[0]);
	if (sig(A)==0 && sig(B)==0) return m[0]; // same line
	if (sig(A)==0) assert(false); //交点を持たない．
	return m[0] + B / A * m.vec();
}

bool parallel(const L &l, const L &m) { return eq<P>(cross(l.vec(), m.vec()), 0); }
bool sameline(const L &l, const L &m) { return parallel(l, m) && eq<P>(cross(l.vec(), m[1]-l[0]), 0); }

// オーバーラップした線分を1つにマージする．
// O(n^2)
vector<L> merge_segments(vector<L>& ss){
	REP(i,ss.size())if(ss[i][1]<ss[i][0])swap(ss[i][0],ss[i][1]);
	REP(i,ss.size())FOR(j,i+1,ss.size()){
		if(sameline(ss[i],ss[j]) && !ccw(ss[i][0],ss[i][1],ss[j][0])){
			ss[i] = L(min(ss[i][0],ss[j][0]), max(ss[i][1],ss[j][1]));
			ss[j--]=ss.back();ss.pop_back();
		}
	}
	return ss;
}

// 線分アレンジメント
// ps[i]=頂点iに対応するP
// O(n^2logn)
// 制約 : 線分のオーバーラップがない．
Graph segmentArrangement(vector<L> ss, vector<P> &ps) {
	vector<vector<D>> vs(ss.size());
	REP(i,ss.size()){vs[i].push_back(0);vs[i].push_back(abs(ss[i][1]-ss[i][0]));}
	REP(i,ss.size())REP(j,ps.size())if(isIntersectSP(ss[i], ps[j]))
		vs[i].push_back(abs(ps[j]-ss[i][0]));
	
	REP(i,ss.size())FOR(j,i+1,ss.size()){
		L& a=ss[i],b=ss[j];
		if(isIntersectSS(a,b)){
			P p = crosspoint(a,b);
			vs[i].push_back(abs(p-a[0]));vs[j].push_back(abs(p-b[0]));				
		}
	}
	REP(i,vs.size()){sort(ALL(vs[i]));vs[i].erase(unique(ALL(vs[i]),eq<D>),vs[i].end());}
	REP(i,vs.size())REP(j,vs[i].size())ps.push_back(ss[i][0]+vs[i][j]*ss[i].vec()/abs(ss[i].vec()));
	sort(ALL(ps));UNIQUE(ps);

	Graph g(ps.size());
	REP(i,vs.size()){
		vector<D>& cut=vs[i];
		REP(j,cut.size()-1){
			P a = ss[i][0] + vs[i][j]*ss[i].vec()/abs(ss[i].vec()),b = ss[i][0] + vs[i][j+1]*ss[i].vec()/abs(ss[i].vec());
			int f=distance(ps.begin(),lower_bound(ALL(ps),a)), t=distance(ps.begin(),lower_bound(ALL(ps),b));
			g[f].push_back(Edge(f,t,abs(a-b)));g[t].push_back(Edge(t,f,abs(a-b)));
		}
	}
	return g;
}

struct Task{
    int prev,pos;Cost cost;
    Task(int prev,int pos,Cost cost)
        :prev(prev),pos(pos),cost(cost){};
    bool operator>(const Task& r) const{ return cost > r.cost;}
};

//verified by codoforces 144D http://codeforces.com/contest/144/submission/4976825
// // 負の辺がない
// // O(E*logV)
vector<Cost> dijkstra(const Graph& g,const int s,vector<int>& prev){
    const int V=g.size();
    vector<Cost> d(V,CINF);d[s]=0;
    fill(ALL(prev), -2);
    
    priority_queue<Task,vector<Task>,greater<Task> > que;que.push(Task(-1,s,0));// [ ,e,,f, ] <=> e.cost < e.cost
    vector<bool> visited(V);
    while(!que.empty()){
        Task task=que.top();que.pop();
        if(visited[task.pos])continue;
        visited[task.pos]=true;
        prev[task.pos]=task.prev;
        EACH(e,g[task.pos])if(d[e->to]>d[e->from]+e->cost){
            d[e->to]=d[e->from]+e->cost;
            que.push(Task(e->from,e->to,d[e->to]));
        }
    }
    return d;
}
vector<Cost> dijkstra(const Graph& g,const int s){
    vector<int> prev(g.size());return dijkstra(g,s,prev);
}

int main(){
	// ifstream cin( "in" );
	// ofstream cout( "out" );
	cout << fixed <<setprecision(20);
	cerr << fixed <<setprecision(20);
	cin.tie(0); ios::sync_with_stdio(false);

	while(true){
		int N;cin >> N;if(N==0)break;
		vector<L> ls(N);REP(i,N) cin >> ls[i];
		P p;cin >> p;
		vector<P> ps;ps.push_back(p);
		Graph g=segmentArrangement(ls,ps);
		
		int si=-1;REP(i,ps.size())if(p==ps[i])si=i;
		vector<Cost> ds = dijkstra(g,si);

		D Mv=*max_element(ALL(ds));
		REP(i,g.size())EACH(e,g[i]){
			D a=abs(ds[e->from]-ds[e->to]);
			D d=abs(ps[e->from]-ps[e->to]);
			Mv=max(Mv,min(ds[e->from],ds[e->to])+(a+d)/2);
		}
		cout << Mv <<endl;
	}
	return 0;
}
accuracy: 1
time_ms: 1130
memory_kb: 13256
final_rank: 5

code_snippet: #include <cassert>// c
#include <iostream>// io
#include <iomanip>
#include <fstream>
#include <sstream>
#include <vector>// container
#include <map>
#include <set>
#include <queue>
#include <bitset>
#include <stack>
#include <algorithm>// other
#include <utility>
#include <complex>
#include <numeric>
#include <functional>
#include <random>
#include <regex>
using namespace std;
typedef long long ll;

#define ALL(c) (c).begin(),(c).end()
#define FOR(i,l,r) for(int i=(int)l;i<(int)r;++i)
#define REP(i,n) FOR(i,0,n)
#define FORr(i,l,r) for(int i=(int)r-1;i>=(int)l;--i)
#define REPr(i,n) FORr(i,0,n)
#define EACH(i,c) for(__typeof((c).begin()) i=(c).begin(); i!=(c).end(); ++i)
#define IN(l,v,r) ((l)<=(v) && (v)<(r))
#define UNIQUE(v) v.erase(unique(ALL(v)),v.end())

// must template
typedef long double D;
const D INF = 1e20,EPS = 1e-10;

int sig(D a,D b=0){return a<b-EPS?-1:a>b+EPS?1:0;}
bool eq(D a,D b){ return sig(abs(a-b))==0;}
// D norm(D a){ return a*a;}

typedef D Cost;Cost CINF=1e20;
struct Edge{
	int from,to;Cost cost;
	Edge(int from,int to,Cost cost) : from(from),to(to),cost(cost) {};
	bool operator<(Edge r) const{return cost<r.cost;}
	bool operator>(Edge r) const{return cost>r.cost;}
};
typedef vector<vector<Edge> >  Graph;
typedef complex<D> P;
#define X real()
#define Y imag()

bool eq(const P& a,const P& b){ return sig(abs(a-b))==0;}
bool compX (const P& a,const P& b){return sig(a.X,b.X)!=0 ? a.X < b.X : a.Y < b.Y;}

istream& operator >> (istream& is,P& p){D x,y;is >> x >> y;p=P(x,y);return is;}

namespace std{
	bool operator <  (const P& a,const P& b){return compX(a,b);}
  	bool operator == (const P& a,const P& b){return eq(a,b);}
};

// a×b
D cross(const P& a,const P& b){return imag(conj(a)*b);}
// a・b
D dot(const P& a,const P& b) {return real(conj(a)*b);}

int ccw(const P& a,P b,P c){
	b -= a; c -= a;
	if (sig(cross(b,c)) > 0)   return +1;       // counter clockwise
	if (sig(cross(b,c)) < 0)   return -1;       // clockwise
	if (sig(dot(b,c)) < 0)     return +2;       // c--a--b on line
	if (sig(norm(b),norm(c))<0) return -2;       // a--b--c on line
	return 0; //a--c--b on line or c==a or c==b
}

//直線・線分
struct L : public vector<P> {
	P vec() const {return this->at(1)-this->at(0);}
	L(const P &a, const P &b){push_back(a); push_back(b);}
	L(){push_back(P(0,0));push_back(P(0,0));}
};
istream& operator >> (istream& is,L& l){is >> l[0] >> l[1];return is;}

bool isIntersectLL(const L &l, const L &m) {
 	return sig(cross(l.vec(), m.vec()))!=0 || // non-parallel
	sig(cross(l.vec(), m[0]-l[0])) == 0;   // same line
}
bool isIntersectLS(const L &l, const L &s) {
	return sig(cross(l.vec(), s[0]-l[0])*       // s[0] is left of l
		cross(l.vec(), s[1]-l[0]))<=0; // s[1] is right of l
}
bool isIntersectLP(const L &l, const P &p) {return sig(cross(l[1]-p, l[0]-p))==0;}

// verified by ACAC003 B
// http://judge.u-aizu.ac.jp/onlinejudge/creview.jsp?rid=899178&cid=ACAC003
bool isIntersectSS(const L &s, const L &t) {
	return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
		ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}
bool isIntersectSP(const L &s, const P &p) {
	return sig(abs(s[0]-p)+abs(s[1]-p),abs(s[1]-s[0])) <=0; // triangle inequality
}
P crosspoint(const L &l, const L &m) {
	D A = cross(l.vec(), m.vec());
	D B = cross(l.vec(), l[1] - m[0]);
	if (sig(A)==0 && sig(B)==0) return m[0]; // same line
	if (sig(A)==0) assert(false); //交点を持たない．
	return m[0] + B / A * m.vec();
}

bool parallel(const L &l, const L &m) { return eq(cross(l.vec(), m.vec()), 0); }
bool sameline(const L &l, const L &m) { return parallel(l, m) && eq(cross(l.vec(), m[1]-l[0]), 0); }

// 線分アレンジメント
// ps[i]=頂点iに対応するP
// O(n^2logn)
Graph segmentArrangement(vector<L> ss, vector<P> &ps) {
	// merge
	// REP(i,ss.size())if(ss[i][1]<ss[i][0])swap(ss[i][0],ss[i][1]);
	// REP(i,ss.size())FOR(j,i+1,ss.size()){
	// 	if(sameline(ss[i],ss[j]) && !ccw(ss[i][0],ss[i][1],ss[j][0])){
	// 		ss[i] = L(min(ss[i][0],ss[j][0]), max(ss[i][1],ss[j][1]));
	// 		// swap(ss[j],ss.back());
	// 		ss[j--] = ss.back();
	// 		ss.pop_back();
	// 	}
	// }
	vector<vector<D>> vs(ss.size());
	REP(i,ss.size()){
		vs[i].push_back(0);vs[i].push_back(abs(ss[i][1]-ss[i][0]));
		REP(j,ps.size())if (isIntersectSP(ss[i], ps[j]))
			vs[i].push_back(abs(ps[j]-ss[i][0]));
	}
	REP(i,ss.size())FOR(j,i+1,ss.size()){
		L a=ss[i],b=ss[j];
		if(isIntersectSS(a,b)){
			P p = crosspoint(a,b);
			vs[i].push_back(abs(p-ss[i][0]));vs[j].push_back(abs(p-ss[j][0]));				
		}
	}
	REP(i,vs.size()){sort(ALL(vs[i]));vs[i].erase(unique(ALL(vs[i]),[](D a,D b)->bool{return abs(a-b)<EPS;}),vs[i].end());}
	REP(i,vs.size())REP(j,vs[i].size())ps.push_back(ss[i][0]+vs[i][j]*ss[i].vec()/abs(ss[i].vec()));
	sort(ALL(ps));UNIQUE(ps);
	// ps.erase(unique(ALL(ps),[](const P& a,const P& b)->bool{return eq(a,b);}),ps.end());
	// cerr << ps.size()<<endl;
	// REP(i,ps.size())cerr << ps[i] <<endl;
	// cerr << endl;
	Graph g(ps.size());
	REP(i,vs.size()){
		vector<D>& cut=vs[i];
		REP(j,cut.size()-1){
			P a = ss[i][0] + vs[i][j]*ss[i].vec()/abs(ss[i].vec()),b = ss[i][0] +  vs[i][j+1]*ss[i].vec()/abs(ss[i].vec());
			int f=distance(ps.begin(), lower_bound(ALL(ps),a,[](const P& a,const P& b)->bool{return !eq(a.X,b.X)?a.X<b.X:a.Y+EPS<b.Y;})),
				t=distance(ps.begin(), lower_bound(ALL(ps),b,[](const P& a,const P& b)->bool{return !eq(a.X,b.X)?a.X<b.X:a.Y+EPS<b.Y;}));
			// cerr << f <<" " << t <<endl;
			// cerr << a <<" " << b <<endl;
			// cerr << compX(ps[9],b)<<endl;
			// cerr << compX(ps[10],b)<<endl;

			g[f].push_back(Edge(f,t,abs(a-b)));
			g[t].push_back(Edge(t,f,abs(a-b)));
		}
	}
	return g;
}

struct Task{
    int prev,pos;Cost cost;
    Task(int prev,int pos,Cost cost)
        :prev(prev),pos(pos),cost(cost){};
    bool operator>(const Task& r) const{ return cost > r.cost;}
};

//verified by codoforces 144D http://codeforces.com/contest/144/submission/4976825
// // 負の辺がない
// // O(E*logV)
vector<Cost> dijkstra(const Graph& g,const int s,vector<int>& prev){
    const int V=g.size();
    vector<Cost> d(V,CINF);d[s]=0;
    fill(ALL(prev), -2);
    
    priority_queue<Task,vector<Task>,greater<Task> > que;que.push(Task(-1,s,0));// [ ,e,,f, ] <=> e.cost < e.cost
    vector<bool> visited(V);
    while(!que.empty()){
        Task task=que.top();que.pop();
        if(visited[task.pos])continue;
        visited[task.pos]=true;
        prev[task.pos]=task.prev;
        EACH(e,g[task.pos])if(d[e->to]>d[e->from]+e->cost){
            d[e->to]=d[e->from]+e->cost;
            que.push(Task(e->from,e->to,d[e->to]));
        }
    }
    return d;
}
vector<Cost> dijkstra(const Graph& g,const int s){
    vector<int> prev(g.size());return dijkstra(g,s,prev);
}

int main(){
	// ifstream cin( "in" );
	// ofstream cout( "out" );
	cout << fixed <<setprecision(20);
	cerr << fixed <<setprecision(20);
	cin.tie(0); ios::sync_with_stdio(false);

	while(true){
		int N;cin >> N;if(N==0)break;
		vector<L> ls(N);REP(i,N) cin >> ls[i];
		P p;cin >> p;
		vector<P> ps;ps.push_back(p);
		Graph g=segmentArrangement(ls,ps);
		
		int si=-1;REP(i,ps.size())if(p==ps[i])si=i;
		vector<Cost> ds = dijkstra(g,si);

		// cout << ps.size() <<endl;
		// REP(i,ps.size())cout << ps[i]<<endl;
		//check
		D Mv=*max_element(ALL(ds));
		REP(i,g.size())EACH(e,g[i]){
			if (eq(abs(ds[e->from] - ds[e->to]), abs(ps[e->from] - ps[e->to]))) continue;
            
			D a=abs(ds[e->from]-ds[e->to]);
			D d=abs(ps[e->from]-ps[e->to]);
			Mv=max(Mv,min(ds[e->from],ds[e->to])+(a+d)/2);
		}
		cout << Mv <<endl;
	}
	return 0;
}
accuracy: 1
time_ms: 1280
memory_kb: 13784
final_rank: 7

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-8)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
#define equals(a,b) (fabs((a)-(b)) < EPS)

using namespace std;

class Point{
public:
  double x,y;
  Point(double x = 0,double y = 0): x(x),y(y){}
  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }
  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:(!equals(y,p.y)&&y<p.y); }
  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }
};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
 bool operator == (const Segment& p)const { return ( p.p1 == p1 && p.p2 == p2 ) || ( p.p1 == p2 && p.p2 == p1 ); }
};

typedef Point Vector;
typedef Segment Line;

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }
double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }
double norm(Point a){ return a.x*a.x+a.y*a.y; }
double abs(Point a){ return sqrt(norm(a)); }

int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

bool intersectSS(Line s, Line t) {
  return ccw(s.p1,s.p2,t.p1)*ccw(s.p1,s.p2,t.p2) <= 0 &&
         ccw(t.p1,t.p2,s.p1)*ccw(t.p1,t.p2,s.p2) <= 0;
}
bool intersectSP(Line s, Point p) { return abs(s.p1-p)+abs(s.p2-p)-abs(s.p2-s.p1) < EPS; }

Point projection(Line l,Point p) {
  double t = dot(p-l.p1, l.p1-l.p2) / norm(l.p1-l.p2);
  return l.p1 + (l.p1-l.p2)*t;
}

Point reflection(Line l,Point p) { return p + (projection(l, p) - p) * 2; }

Point crosspoint(Line l,Line m){
  double A = cross(l.p2-l.p1,m.p2-m.p1);
  double B = cross(l.p2-l.p1,l.p2-m.p1);
  if(abs(A) < EPS && abs(B) < EPS){
    vector<Point> vec;
    vec.push_back(l.p1),vec.push_back(l.p2),vec.push_back(m.p1),vec.push_back(m.p2);
    sort(vec.begin(),vec.end());
    assert(vec[1] == vec[2]); //同じセグメントかもよ
    return vec[1];
  }
  if(abs(A) < EPS)assert(false);
  return m.p1 + (m.p2-m.p1)*(B/A);
}

struct Edge {
  int from,to;
  double cost;
  Edge(int from=0,int to=0,double cost=0):from(from),to(to),cost(cost){}
  bool operator < (const Edge& a)const { return !equals(cost,a.cost) && cost < a.cost; }
};

Point sp;

vector<vector<Edge> > segmentArrangement(vector<Segment> &vs,vector<Point> &ps) {
  ps.push_back(sp);
  rep(i,vs.size()) ps.push_back( (vs[i].p1+vs[i].p2) / 2.0 );
  rep(i,vs.size()) ps.push_back(vs[i].p1), ps.push_back(vs[i].p2);
  rep(i,vs.size()) REP(j,i+1,vs.size()) if(intersectSS(vs[i],vs[j])) ps.push_back(Point(crosspoint(vs[i],vs[j])));
  sort(ps.begin(),ps.end());  
  ps.erase(unique(ps.begin(),ps.end()),ps.end());

  vector<vector<Edge> > ret(ps.size());

  for(int i=0;i<vs.size();i++){
    vector<pair<double,int> > list;
    rep(j,ps.size()) if(intersectSP(vs[i],ps[j]))list.push_back(pair<double,int>(norm(vs[i].p1-ps[j]),j));
    sort(list.begin(),list.end());
    for(int j=0;j+1<list.size();++j) {
      int from = list[j].second, to = list[j+1].second;
      double cost = abs(ps[from]-ps[to]);
      ret[from].push_back(Edge(from,to,cost));
      ret[to].push_back(Edge(to,from,cost));
    }
  }  
  return ret;
}

int E;
vector<Segment> segs;

bool  LT(double a,double b) { return !equals(a,b) && a < b; }
bool LTE(double a,double b) { return  equals(a,b) || a < b; }

// --作成中-- 

Point vir;
bool comp_dist(const Point &a,const Point &b){ return LT(abs(vir-a),abs(vir-b)); }

const int MAX_N = 2000;
int uf[MAX_N];
void init(int N=MAX_N) { rep(i,N) uf[i] = i; }
int find(int x) { 
  if( x == uf[x] ) return x;
  return uf[x] = find(uf[x]);
}
void unit(int x,int y){
  x = find(x), y = find(y);
  if( x != y ) uf[x] = y;  
}

void segmentMerge(vector<Segment> &vec,vector<Segment> &ret){
  init(vec.size());
  rep(i,vec.size()) {
    rep(j,vec.size()) {
      if( equals(cross(vec[i].p1-vec[i].p2,vec[j].p1-vec[j].p2),0.0) && intersectSS(vec[i],vec[j]) ) unit(i,j);
    }
  }

  ret.clear();
  vector<int> color;
  rep(i,vec.size()) color.push_back(find(i));
  sort(color.begin(),color.end());
  color.erase(unique(color.begin(),color.end()),color.end());
  rep(i,color.size()) {
    vector<Point> vp;
    rep(j,vec.size()) if( color[i] == find(j) ) vp.push_back(vec[j].p1), vp.push_back(vec[j].p2);
    sort(vp.begin(),vp.end());
    vp.erase(unique(vp.begin(),vp.end()),vp.end());
    assert( vp.size() >= 2 ); // 線分じゃなくて点
    vir = vp[0];
    sort(vp.begin(),vp.end(),comp_dist);
    ret.push_back(Segment(vp.front(),vp.back()));
  }
}

// --作成中--

const double DINF = 1e20;

struct Data {
  int cur;
  double weight;
  bool operator < ( const Data &data ) const { return !equals(weight,data.weight) && weight > data.weight; }
};

void dijkstra(vector<vector<Edge> > &G,vector<Point> &ps){
  int sindex = -1;
  rep(i,(int)ps.size()) if( ps[i] == sp ) { sindex = i; break; }

  int V = ps.size();
  priority_queue<Data> Q;
  Q.push((Data){sindex,0});
  vector<double> mindist(V,DINF);
  mindist[sindex] = 0;
  while( !Q.empty() ){
    Data data = Q.top(); Q.pop();
    if( LT(mindist[data.cur],data.weight) ) continue;
    rep(i,G[data.cur].size()){
      int to = G[data.cur][i].to;
      if( LT(data.weight+G[data.cur][i].cost,mindist[to]) ){
        mindist[to] = data.weight+G[data.cur][i].cost;
        Q.push((Data){to,mindist[to]});
      }
    }
  }

  double maxi = 0;
  rep(i,V) {
    assert( !equals(DINF,mindist[i]) );
    maxi = max(maxi,mindist[i]);
  }
  printf("%.10lf\n",maxi);
}

void compute(){
  vector<Segment> buf;
  segmentMerge(segs,buf);  
  vector<Point> ps;
  vector<vector<Edge> > G = segmentArrangement(buf,ps);
  dijkstra(G,ps);
}

int main(){
  while( cin >> E, E ){
    segs.resize(E);
    rep(i,E) cin >> segs[i].p1.x >> segs[i].p1.y >> segs[i].p2.x >> segs[i].p2.y;
    cin >> sp.x >> sp.y;
    compute();
  }
  return 0;
}
accuracy: 1
time_ms: 5170
memory_kb: 5996
final_rank: 11

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-8)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
#define equals(a,b) (fabs((a)-(b)) < EPS)

using namespace std;

class Point{
public:
  double x,y;

  Point(double x = 0,double y = 0): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }

  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:(!equals(y,p.y)&&y<p.y); }

  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }

};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
 bool operator == (const Segment& p)const { return ( p.p1 == p1 && p.p2 == p2 ) || ( p.p1 == p2 && p.p2 == p1 ); }
};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream& operator << (ostream& os,const Point& a){ os << "(" << a.x << "," << a.y << ")"; }

ostream& operator << (ostream& os,const Segment& a){ os << "( " << a.p1 << " , " << a.p2 << " )"; }

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

//rad は角度をラジアンで持たせること
Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

// 度をラジアンに変換
double toRad(double agl){ return agl*M_PI/180.0; }

// a => prev, b => cur, c=> next
// prev から cur へ行って next へ行く際の角度を求める
double getArg(Point a,Point b,Point c){
  double arg1 = atan2(b.y-a.y,b.x-a.x);
  double arg2 = atan2(c.y-b.y,c.x-b.x);
  double arg = fabs( arg1 - arg2 );
  while( arg > M_PI ) arg -= 2.0 * M_PI;
  return fabs(arg);
}


int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

bool intersectLL(Line l, Line m) {
  return abs(cross(l.p2-l.p1, m.p2-m.p1)) > EPS || // non-parallel
         abs(cross(l.p2-l.p1, m.p1-l.p1)) < EPS;   // same line
}
bool intersectLS(Line l, Line s) {
  return cross(l.p2-l.p1, s.p1-l.p1)*       // s[0] is left of l
         cross(l.p2-l.p1, s.p2-l.p1) < EPS; // s[1] is right of l
}
bool intersectLP(Line l,Point p) {
  return abs(cross(l.p2-p, l.p1-p)) < EPS;
}
bool intersectSS(Line s, Line t) {
  return ccw(s.p1,s.p2,t.p1)*ccw(s.p1,s.p2,t.p2) <= 0 &&
         ccw(t.p1,t.p2,s.p1)*ccw(t.p1,t.p2,s.p2) <= 0;
}
bool intersectSP(Line s, Point p) {
  return abs(s.p1-p)+abs(s.p2-p)-abs(s.p2-s.p1) < EPS; // triangle inequality
}

Point projection(Line l,Point p) {
  double t = dot(p-l.p1, l.p1-l.p2) / norm(l.p1-l.p2);
  return l.p1 + (l.p1-l.p2)*t;
}
Point reflection(Line l,Point p) {
  return p + (projection(l, p) - p) * 2;
}
double distanceLP(Line l, Point p) {
  return abs(p - projection(l, p));
}
double distanceLL(Line l, Line m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m.p1);
}

double distanceLS(Line l, Line s) {
  if (intersectLS(l, s)) return 0;
  return min(distanceLP(l, s.p1), distanceLP(l, s.p2));
}
double distanceSP(Line s, Point p) {
  Point r = projection(s, p);
  if (intersectSP(s, r)) return abs(r - p);
  return min(abs(s.p1 - p), abs(s.p2 - p));
}

double distanceSS(Line s, Line t) {
  if (intersectSS(s, t)) return 0;
  return min(min(distanceSP(s, t.p1), distanceSP(s, t.p2)),
             min(distanceSP(t, s.p1), distanceSP(t, s.p2)));
}

Point crosspoint(Line l,Line m){
  double A = cross(l.p2-l.p1,m.p2-m.p1);
  double B = cross(l.p2-l.p1,l.p2-m.p1);
  if(abs(A) < EPS && abs(B) < EPS){
    vector<Point> vec;
    vec.push_back(l.p1),vec.push_back(l.p2),vec.push_back(m.p1),vec.push_back(m.p2);
    sort(vec.begin(),vec.end());
    assert(vec[1] == vec[2]); //同じセグメントかもよ
    return vec[1];
    //return m.p1;
  }
  if(abs(A) < EPS)assert(false);
  return m.p1 + (m.p2-m.p1)*(B/A);
}

struct Edge {
  int from,to;
  double cost;
  Edge(int from=0,int to=0,double cost=0):from(from),to(to),cost(cost){}
  bool operator < (const Edge& a)const { return !equals(cost,a.cost) && cost < a.cost; }
};

Point sp;

vector<vector<Edge> > segmentArrangement(vector<Segment> &vs,vector<Point> &ps) {
  ps.push_back(sp);

  rep(i,vs.size()) ps.push_back( (vs[i].p1+vs[i].p2) / 2.0 );

  rep(i,vs.size()) ps.push_back(vs[i].p1), ps.push_back(vs[i].p2);
  rep(i,vs.size()) REP(j,i+1,vs.size()) if(intersectSS(vs[i],vs[j])) ps.push_back(Point(crosspoint(vs[i],vs[j])));

  sort(ps.begin(),ps.end());  
  ps.erase(unique(ps.begin(),ps.end()),ps.end());

  vector<vector<Edge> > ret(ps.size());

  for(int i=0;i<vs.size();i++){
    vector<pair<double,int> > list;
    rep(j,ps.size()) if(intersectSP(vs[i],ps[j]))list.push_back(pair<double,int>(norm(vs[i].p1-ps[j]),j));
    sort(list.begin(),list.end());
    for(int j=0;j+1<list.size();++j) {
      int from = list[j].second, to = list[j+1].second;
      double cost = abs(ps[from]-ps[to]);
      ret[from].push_back(Edge(from,to,cost));
      ret[to].push_back(Edge(to,from,cost));
    }
  }  
  return ret;
}

int E;
vector<Segment> segs;

bool  LT(double a,double b) { return !equals(a,b) && a < b; }
bool LTE(double a,double b) { return  equals(a,b) || a < b; }

// --作成中-- 

Point vir;
bool comp_dist(const Point &a,const Point &b){ return LT(abs(vir-a),abs(vir-b)); }

const int MAX_N = 2000;
int uf[MAX_N];
void init(int N=MAX_N) { rep(i,N) uf[i] = i; }
int find(int x) { 
  if( x == uf[x] ) return x;
  return uf[x] = find(uf[x]);
}
void unit(int x,int y){
  x = find(x), y = find(y);
  if( x != y ) uf[x] = y;  
}

void segmentMerge(vector<Segment> &vec,vector<Segment> &ret){
  init(vec.size());
  rep(i,vec.size()) {
    rep(j,vec.size()) {
      if( equals(cross(vec[i].p1-vec[i].p2,vec[j].p1-vec[j].p2),0.0) && intersectSS(vec[i],vec[j]) ) unit(i,j);
    }
  }

  ret.clear();
  vector<int> color;
  rep(i,vec.size()) color.push_back(find(i));
  sort(color.begin(),color.end());
  color.erase(unique(color.begin(),color.end()),color.end());
  rep(i,color.size()) {
    vector<Point> vp;
    rep(j,vec.size()) if( color[i] == find(j) ) vp.push_back(vec[j].p1), vp.push_back(vec[j].p2);
    sort(vp.begin(),vp.end());
    vp.erase(unique(vp.begin(),vp.end()),vp.end());
    assert( vp.size() >= 2 ); // 線分じゃなくて点
    vir = vp[0];
    sort(vp.begin(),vp.end(),comp_dist);
    ret.push_back(Segment(vp.front(),vp.back()));
  }
}

// --作成中--

const double DINF = 1e20;

struct Data {
  int cur;
  double weight;
  bool operator < ( const Data &data ) const { return !equals(weight,data.weight) && weight > data.weight; }
};

void dijkstra(vector<vector<Edge> > &G,vector<Point> &ps){
  int sindex = -1;
  rep(i,(int)ps.size()) if( ps[i] == sp ) { sindex = i; break; }
  assert( sindex != -1 );

  int V = ps.size();
  priority_queue<Data> Q;
  Q.push((Data){sindex,0});
  vector<double> mindist(V,DINF);
  mindist[sindex] = 0;
  while( !Q.empty() ){
    Data data = Q.top(); Q.pop();
    
    if( LT(mindist[data.cur],data.weight) ) continue;

    rep(i,G[data.cur].size()){
      int to = G[data.cur][i].to;
      if( LT(data.weight+G[data.cur][i].cost,mindist[to]) ){
        mindist[to] = data.weight+G[data.cur][i].cost;
        Q.push((Data){to,mindist[to]});
      }
    }

  }

  double maxi = 0;
  rep(i,V) {
    assert( !equals(DINF,mindist[i]) );
    maxi = max(maxi,mindist[i]);
  }

  printf("%.10lf\n",maxi);

}

void compute(){
  vector<Segment> buf = segs;
  //segmentMerge(segs,buf);  

  vector<Point> ps;
  vector<vector<Edge> > G = segmentArrangement(buf,ps);

  dijkstra(G,ps);

}

int main(){
  while( cin >> E, E ){
    segs.resize(E);
    rep(i,E) cin >> segs[i].p1.x >> segs[i].p1.y >> segs[i].p2.x >> segs[i].p2.y;
    cin >> sp.x >> sp.y;
    compute();
  }
  return 0;
}
accuracy: 1
time_ms: 5130
memory_kb: 5968
final_rank: 10

code_snippet: #include<bits/stdc++.h>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-8)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0
#define equals(a,b) (fabs((a)-(b)) < EPS)

using namespace std;

class Point{
public:
  double x,y;

  Point(double x = 0,double y = 0): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }

  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:(!equals(y,p.y)&&y<p.y); }

  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }

};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
 bool operator == (const Segment& p)const { return ( p.p1 == p1 && p.p2 == p2 ) || ( p.p1 == p2 && p.p2 == p1 ); }
};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream& operator << (ostream& os,const Point& a){ os << "(" << a.x << "," << a.y << ")"; }

ostream& operator << (ostream& os,const Segment& a){ os << "( " << a.p1 << " , " << a.p2 << " )"; }

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

//rad は角度をラジアンで持たせること
Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

// 度をラジアンに変換
double toRad(double agl){ return agl*M_PI/180.0; }

// a => prev, b => cur, c=> next
// prev から cur へ行って next へ行く際の角度を求める
double getArg(Point a,Point b,Point c){
  double arg1 = atan2(b.y-a.y,b.x-a.x);
  double arg2 = atan2(c.y-b.y,c.x-b.x);
  double arg = fabs( arg1 - arg2 );
  while( arg > M_PI ) arg -= 2.0 * M_PI;
  return fabs(arg);
}


int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

bool intersectLL(Line l, Line m) {
  return abs(cross(l.p2-l.p1, m.p2-m.p1)) > EPS || // non-parallel
         abs(cross(l.p2-l.p1, m.p1-l.p1)) < EPS;   // same line
}
bool intersectLS(Line l, Line s) {
  return cross(l.p2-l.p1, s.p1-l.p1)*       // s[0] is left of l
         cross(l.p2-l.p1, s.p2-l.p1) < EPS; // s[1] is right of l
}
bool intersectLP(Line l,Point p) {
  return abs(cross(l.p2-p, l.p1-p)) < EPS;
}
bool intersectSS(Line s, Line t) {
  return ccw(s.p1,s.p2,t.p1)*ccw(s.p1,s.p2,t.p2) <= 0 &&
         ccw(t.p1,t.p2,s.p1)*ccw(t.p1,t.p2,s.p2) <= 0;
}
bool intersectSP(Line s, Point p) {
  return abs(s.p1-p)+abs(s.p2-p)-abs(s.p2-s.p1) < EPS; // triangle inequality
}

Point projection(Line l,Point p) {
  double t = dot(p-l.p1, l.p1-l.p2) / norm(l.p1-l.p2);
  return l.p1 + (l.p1-l.p2)*t;
}
Point reflection(Line l,Point p) {
  return p + (projection(l, p) - p) * 2;
}
double distanceLP(Line l, Point p) {
  return abs(p - projection(l, p));
}
double distanceLL(Line l, Line m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m.p1);
}

double distanceLS(Line l, Line s) {
  if (intersectLS(l, s)) return 0;
  return min(distanceLP(l, s.p1), distanceLP(l, s.p2));
}
double distanceSP(Line s, Point p) {
  Point r = projection(s, p);
  if (intersectSP(s, r)) return abs(r - p);
  return min(abs(s.p1 - p), abs(s.p2 - p));
}

double distanceSS(Line s, Line t) {
  if (intersectSS(s, t)) return 0;
  return min(min(distanceSP(s, t.p1), distanceSP(s, t.p2)),
             min(distanceSP(t, s.p1), distanceSP(t, s.p2)));
}

Point crosspoint(Line l,Line m){
  double A = cross(l.p2-l.p1,m.p2-m.p1);
  double B = cross(l.p2-l.p1,l.p2-m.p1);
  if(abs(A) < EPS && abs(B) < EPS){
    vector<Point> vec;
    vec.push_back(l.p1),vec.push_back(l.p2),vec.push_back(m.p1),vec.push_back(m.p2);
    sort(vec.begin(),vec.end());
    assert(vec[1] == vec[2]); //同じセグメントかもよ
    return vec[1];
    //return m.p1;
  }
  if(abs(A) < EPS)assert(false);
  return m.p1 + (m.p2-m.p1)*(B/A);
}

struct Edge {
  int from,to;
  double cost;
  Edge(int from=0,int to=0,double cost=0):from(from),to(to),cost(cost){}
  bool operator < (const Edge& a)const { return !equals(cost,a.cost) && cost < a.cost; }
};

Point sp;

vector<vector<Edge> > segmentArrangement(vector<Segment> &vs,vector<Point> &ps) {
  ps.push_back(sp);

  rep(i,vs.size()) ps.push_back( (vs[i].p1+vs[i].p2) / 2.0 );

  rep(i,vs.size()) ps.push_back(vs[i].p1), ps.push_back(vs[i].p2);
  rep(i,vs.size()) REP(j,i+1,vs.size()) if(intersectSS(vs[i],vs[j])) ps.push_back(Point(crosspoint(vs[i],vs[j])));

  sort(ps.begin(),ps.end());  
  ps.erase(unique(ps.begin(),ps.end()),ps.end());

  vector<vector<Edge> > ret(ps.size());

  for(int i=0;i<vs.size();i++){
    vector<pair<double,int> > list;
    rep(j,ps.size()) if(intersectSP(vs[i],ps[j]))list.push_back(pair<double,int>(norm(vs[i].p1-ps[j]),j));
    sort(list.begin(),list.end());
    for(int j=0;j+1<list.size();++j) {
      int from = list[j].second, to = list[j+1].second;
      double cost = abs(ps[from]-ps[to]);
      ret[from].push_back(Edge(from,to,cost));
      ret[to].push_back(Edge(to,from,cost));
    }
  }  
  return ret;
}

int E;
vector<Segment> segs;

bool  LT(double a,double b) { return !equals(a,b) && a < b; }
bool LTE(double a,double b) { return  equals(a,b) || a < b; }

// --作成中-- 

Point vir;
bool comp_dist(const Point &a,const Point &b){ return LT(abs(vir-a),abs(vir-b)); }

const int MAX_N = 2000;
int uf[MAX_N];
void init(int N=MAX_N) { rep(i,N) uf[i] = i; }
int find(int x) { 
  if( x == uf[x] ) return x;
  return uf[x] = find(uf[x]);
}
void unit(int x,int y){
  x = find(x), y = find(y);
  if( x != y ) uf[x] = y;  
}

void segmentMerge(vector<Segment> &vec,vector<Segment> &ret){
  init(vec.size());
  rep(i,vec.size()) {
    rep(j,vec.size()) {
      if( equals(cross(vec[i].p1-vec[i].p2,vec[j].p1-vec[j].p2),0.0) && intersectSS(vec[i],vec[j]) ) unit(i,j);
    }
  }

  ret.clear();
  vector<int> color;
  rep(i,vec.size()) color.push_back(find(i));
  sort(color.begin(),color.end());
  color.erase(unique(color.begin(),color.end()),color.end());
  rep(i,color.size()) {
    vector<Point> vp;
    rep(j,vec.size()) if( color[i] == find(j) ) vp.push_back(vec[j].p1), vp.push_back(vec[j].p2);
    sort(vp.begin(),vp.end());
    vp.erase(unique(vp.begin(),vp.end()),vp.end());
    assert( vp.size() >= 2 ); // 線分じゃなくて点
    vir = vp[0];
    sort(vp.begin(),vp.end(),comp_dist);
    ret.push_back(Segment(vp.front(),vp.back()));
  }
}

// --作成中--

const double DINF = 1e20;

struct Data {
  int cur;
  double weight;
  bool operator < ( const Data &data ) const { return !equals(weight,data.weight) && weight > data.weight; }
};

void dijkstra(vector<vector<Edge> > &G,vector<Point> &ps){
  int sindex = -1;
  rep(i,(int)ps.size()) if( ps[i] == sp ) { sindex = i; break; }
  assert( sindex != -1 );

  int V = ps.size();
  priority_queue<Data> Q;
  Q.push((Data){sindex,0});
  vector<double> mindist(V,DINF);
  mindist[sindex] = 0;
  while( !Q.empty() ){
    Data data = Q.top(); Q.pop();
    
    if( LT(mindist[data.cur],data.weight) ) continue;

    rep(i,G[data.cur].size()){
      int to = G[data.cur][i].to;
      if( LT(data.weight+G[data.cur][i].cost,mindist[to]) ){
        mindist[to] = data.weight+G[data.cur][i].cost;
        Q.push((Data){to,mindist[to]});
      }
    }

  }

  double maxi = 0;
  rep(i,V) {
    assert( !equals(DINF,mindist[i]) );
    maxi = max(maxi,mindist[i]);
  }

  printf("%.10lf\n",maxi);

}

void compute(){
  vector<Segment> buf;
  segmentMerge(segs,buf);  

  //rep(i,buf.size()) cout << i << "-th : " << buf[i] << endl;

  vector<Point> ps;
  vector<vector<Edge> > G = segmentArrangement(buf,ps);

  dijkstra(G,ps);

}

int main(){
  while( cin >> E, E ){
    segs.resize(E);
    rep(i,E) cin >> segs[i].p1.x >> segs[i].p1.y >> segs[i].p2.x >> segs[i].p2.y;
    cin >> sp.x >> sp.y;
    compute();
  }
  return 0;
}
accuracy: 1
time_ms: 5180
memory_kb: 6000
final_rank: 12

code_snippet: #include <iostream>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <cassert>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a,b) (a<(b)?(a=b,1):0)
#define chmin(a,b) (a>(b)?(a=b,1):0)
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
// #define double long double
const int INF = 1<<29;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef pair<int,int> pii;
typedef long long ll;

typedef double Weight;
struct Edge {
  int src, dst;
  Weight weight;
  Edge(int src, int dst, Weight weight) :
    src(src), dst(dst), weight(weight) { }
};

bool operator < (const Edge &e, const Edge &f) {
  return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
    e.src != f.src ? e.src < f.src : e.dst < f.dst;
}

typedef vector<Edge> Edges;
typedef vector<Edges> Graph;


// 道程がいらない場合
vector<Weight> dijkstra(const Graph &g, int s) {
  vector<Weight> dist(g.size(), INF);
  dist[s] = 0;
  priority_queue<Edge> Q; // "e < f" <=> "e.weight > f.weight"
  for (Q.push(Edge(-2, s, 0)); !Q.empty(); ) {
    Edge e = Q.top(); Q.pop();
    if (dist[e.dst] < e.weight) continue;
    FOR(f,g[e.dst]) {
      if (dist[f->dst] > e.weight+f->weight) {
        dist[f->dst] = e.weight+f->weight;
        Q.push(Edge(f->src, f->dst, e.weight+f->weight));
      }
    }
  }
  return dist;
}


typedef complex<double> P;
namespace std {
  bool operator < (const P& a, const P& b) {
    if (abs(a-b)<EPS) return 0;
    return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
  }
}
double cross(const P& a, const P& b) {
  return imag(conj(a)*b);
}
double dot(const P& a, const P& b) {
  return real(conj(a)*b);
}
struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a); push_back(b);
  }
  L() {resize(2);}
};
ostream &operator<<(ostream &os, const L &a) {
  os << a[0] << " -> " << a[1];
  return os;
}

typedef vector<P> G;
#define curr(P, i) P[i]
#define next(P, i) P[(i+1)%P.size()]
struct C {
  P p; double r;
  C(const P &p, double r) : p(p), r(r) { }
};

int ccw(P a, P b, P c) {
  b -= a; c -= a;
  if (cross(b, c) > EPS)   return +1;       // counter clockwise
  if (cross(b, c) < -EPS)   return -1;       // clockwise
  if (dot(b, c) < -EPS)     return +2;       // c--a--b on line
  if (norm(b) < norm(c)) return -2;       // a--b--c on line
  return 0;
}

P rotate(const P &p, double ang) {
  return p * P(cos(ang), sin(ang));
}

P projection(const L &l, const P &p) {
  double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
  return l[0] + t*(l[0]-l[1]);
}
P reflection(const L &l, const P &p) {
  return p + P(2,0) * (projection(l, p) - p);
}

double distanceLP(const L &l, const P &p) {
  return abs(p - projection(l, p));
}

bool intersectSP(const L &s, const P &p) {
  return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS; // triangle inequality
}
bool intersectLL(const L &l, const L &m) {
  return abs(cross(l[1]-l[0], m[1]-m[0])) > EPS || // non-parallel
         abs(cross(l[1]-l[0], m[0]-l[0])) < EPS;   // same line
}
bool intersectLS(const L &l, const L &s) {
  return cross(l[1]-l[0], s[0]-l[0])*       // s[0] is left of l
         cross(l[1]-l[0], s[1]-l[0]) < EPS; // s[1] is right of l
}
bool intersectLP(const L &l, const P &p) {
  return abs(cross(l[1]-p, l[0]-p)) < EPS;
}
bool intersectSS(const L &s, const L &t) {
  return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
         ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}
bool intersectSS2(const L &s, const L &t) {
  if (intersectSP(s,t[0]) || intersectSP(s,t[1]) ||
      intersectSP(t,s[0]) || intersectSP(t,s[1])) return 0;
  return intersectSS(s,t);
}
bool intersectHS(const L &h, const L &s) {
  if (intersectLP(h,s[0]) || intersectLP(h,s[1]) ||
      intersectLP(s,h[0]) || intersectLP(s,h[1])) return 0;
  if (intersectSS(h,s)) return 1;
  if (!intersectLS(h,s)) return 0;
  return (ccw(s[0],s[1],h[0]) == 1) ^ (cross(s[1]-s[0], h[1]-h[0]) > 0);
}

P crosspoint(const L &l, const L &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  if (abs(A) < EPS && abs(B) < EPS) {
    // sameline
    if (intersectSP(l,m[0]) && intersectSP(l,m[1])) return P(0.5)*(m[0]+m[1]);
    if (intersectSP(m,l[0]) && intersectSP(m,l[1])) return P(0.5)*(l[0]+l[1]);
    REP(i,2) REP(j,2)
      if (intersectSP(l,m[i]) && intersectSP(m,l[j])) return P(0.5)*(m[i]+l[j]);
  }
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m[0] + B / A * (m[1] - m[0]);
}

bool EQ(double a, double b) {
  return abs(a-b) < EPS;
}
bool EQP(const P &a, const P &b) {
  return norm(a-b) < EPS*EPS;
}

#define index_of(ps, p) \
  distance(ps.begin(), lower_bound(ps.begin(), ps.end(), p))
Graph arrangement(const vector<L>& segs, vector<P>& pt) {
  vector< vector<double> > V(segs.size());
  for (int i = 0; i < segs.size(); ++i) {
    pt.push_back( segs[i][0] );
    pt.push_back( segs[i][1] );
    V[i].push_back(0);
    V[i].push_back(1);
    for (int j = i+1; j < segs.size(); ++j) {
      L a = segs[i], b = segs[j];
      if (intersectSS(a, b)) {
        double D = cross(b[1]-b[0], a[1]-a[0]);
        if (abs(D) < EPS) continue;
        double t = cross(b[1]-b[0], b[0]-a[0]) / D;
        double s = cross(a[0]-b[0], a[1]-a[0]) / D;
        V[i].push_back(t);
        V[j].push_back(s);
        pt.push_back( a[0]+(a[1]-a[0])*t );
      }
    }
  }
  sort(pt.begin(), pt.end());
  pt.erase(unique(pt.begin(), pt.end(), EQP), pt.end());

  Graph g(pt.size());
  for (int i = 0; i < V.size(); ++i) {
    vector<double>& cut = V[i];
    sort(cut.begin(), cut.end());
    cut.erase(unique(cut.begin(), cut.end(), EQ), cut.end());
    for (int j = 0; j+1 < cut.size(); ++j) {
      P a = segs[i][0] + (segs[i][1] - segs[i][0]) * cut[j];
      P b = segs[i][0] + (segs[i][1] - segs[i][0]) * cut[j+1];
      int src = index_of(pt, a), dst = index_of(pt, b);
      // cout << g.size() << " " << src << " " << dst << " " << abs(a-b) << endl;
      g[src].push_back( Edge(src, dst, abs(a-b)) );
      g[dst].push_back( Edge(dst, src, abs(a-b)) );
    }
  }
  return g;
}

Graph segmentArrangement(const vector<L> &ss, vector<P> &ps) {
  int n = ss.size();
  REP(i,n) {
    ps.push_back( ss[i][0] );
    ps.push_back( ss[i][1] );
    for (int j = i+1; j < ss.size(); ++j)
      if (intersectSS(ss[i], ss[j]))
        ps.push_back( crosspoint(ss[i], ss[j]) );
  }
  sort(ALL(ps)); ps.erase(unique(ALL(ps)), ps.end());

  Graph g(ps.size());
  for (int i = 0; i < ss.size(); ++i) {
    int pre = -1;
    for (int j = 0; j < ps.size(); ++j)
      if (intersectSP(ss[i], ps[j])) {
        if (pre != -1) {
          double d = abs(ps[pre]-ps[j]);
          g[pre].push_back(Edge(pre,j,d));
          g[j].push_back(Edge(j,pre,d));
        }
        pre = j;
      }
  }
  return g;
}

vector<Edge> graph[300000];
int pid[1004][1004];

Graph segmentArrangement2(const vector<L> &ss, vector<P> &ps) {
  memset(pid,-1,sizeof(pid));
  REP(i,300000) graph[i].clear();
  int n = ss.size();
  REP(i,n) {
    int beg = ps.size();
    ps.push_back(ss[i][0]);
    ps.push_back(ss[i][1]);
    REP(j,n) {
      if (i == j) continue;
      if (intersectSS(ss[i],ss[j])) {
        int b = ps.size();
        if (i>j) {
          int a = pid[j][i];
          // cout << ps[a] << " "<< crosspoint(ss[i],ss[j]) << endl;
          graph[a].push_back(Edge(a,b,0));
          graph[b].push_back(Edge(b,a,0));
        } else {
          pid[i][j] = b;
        }
        ps.push_back(crosspoint(ss[i],ss[j]));
      }
    }
    vector<pair<P,int> > v(ps.size()-beg);
    for (int i=beg; i<ps.size(); ++i)
      v[i-beg] = make_pair(ps[i],i);
    sort(ALL(v));
    REP(i,v.size()-1) {
      int a = v[i].second, b = v[i+1].second;
      double c = abs(v[i].first-v[i+1].first);
      graph[a].push_back(Edge(a,b,c));
      graph[b].push_back(Edge(b,a,c));
    }
  }
  Graph g(ps.size());
  REP(i,ps.size()) {
    g[i] = graph[i];
  }
  return g;
}


int main() {
  int n;
  while(cin >> n, n) {
    vector<L> segs;
    REP(i,n) {
      P a, b;
      cin >> a.real() >> a.imag();
      cin >> b.real() >> b.imag();
      segs.push_back(L(a,b));
    }
    P s;
    cin >> s.real() >> s.imag();
    REP(i,n) {
      if (intersectSP(segs[i],s)) {
        segs.push_back(L(segs[i][0],s));
        segs.push_back(L(s,segs[i][1]));
        break;
      }
    }
    vector<P> pv;
    // Graph g = arrangement(segs,pv);
    Graph g = segmentArrangement2(segs,pv);
    int sid = -1;
    REP(i,pv.size()) {
      if (abs(pv[i]-s) < EPS) sid = i;
    }
    assert(sid != -1);
    // REP(i,g.size()) {
    //   cout << i << endl;
    //   FOR(it, g[i]) {
    //     cout << it->dst << " " << it->weight << endl;
    //   }
    // }
    // cout << sid << endl;
    vector<double> dis = dijkstra(g,sid);
    double ans = 0;
    REP(i,g.size()) {
      FOR(it, g[i]) {
        int a = it->src;
        int b = it->dst;
        double x = (dis[b]-dis[a]+it->weight) / 2;
        chmax(ans, dis[a] + x);
      }
    }
    cout << setprecision(10) << fixed << ans << endl;
    // printf("%.10Lf\n", ans);
  }
}
accuracy: 1
time_ms: 700
memory_kb: 25688
final_rank: 9

code_snippet: #include <iostream>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <cassert>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a,b) (a<(b)?(a=b,1):0)
#define chmin(a,b) (a>(b)?(a=b,1):0)
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
#define double long double
const int INF = 1<<29;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef pair<int,int> pii;
typedef long long ll;

typedef double Weight;
struct Edge {
  int src, dst;
  Weight weight;
  Edge(int src, int dst, Weight weight) :
    src(src), dst(dst), weight(weight) { }
};

bool operator < (const Edge &e, const Edge &f) {
  return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
    e.src != f.src ? e.src < f.src : e.dst < f.dst;
}

typedef vector<Edge> Edges;
typedef vector<Edges> Graph;


// テゥツ?禿ァツィツ凝」ツ?古」ツ??」ツつ嘉」ツ?ェテ」ツ??・ツ?エテ・ツ青?
vector<Weight> dijkstra(const Graph &g, int s) {
  vector<Weight> dist(g.size(), INF);
  dist[s] = 0;
  priority_queue<Edge> Q; // "e < f" <=> "e.weight > f.weight"
  for (Q.push(Edge(-2, s, 0)); !Q.empty(); ) {
    Edge e = Q.top(); Q.pop();
    if (dist[e.dst] < e.weight) continue;
    FOR(f,g[e.dst]) {
      if (dist[f->dst] > e.weight+f->weight) {
        dist[f->dst] = e.weight+f->weight;
        Q.push(Edge(f->src, f->dst, e.weight+f->weight));
      }
    }
  }
  return dist;
}


typedef complex<double> P;
namespace std {
  bool operator < (const P& a, const P& b) {
    if (abs(a-b)<EPS) return 0;
    return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
  }
}
double cross(const P& a, const P& b) {
  return imag(conj(a)*b);
}
double dot(const P& a, const P& b) {
  return real(conj(a)*b);
}
struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a); push_back(b);
  }
  L() {resize(2);}
};
ostream &operator<<(ostream &os, const L &a) {
  os << a[0] << " -> " << a[1];
  return os;
}

typedef vector<P> G;
#define curr(P, i) P[i]
#define next(P, i) P[(i+1)%P.size()]
struct C {
  P p; double r;
  C(const P &p, double r) : p(p), r(r) { }
};

int ccw(P a, P b, P c) {
  b -= a; c -= a;
  if (cross(b, c) > EPS)   return +1;       // counter clockwise
  if (cross(b, c) < -EPS)   return -1;       // clockwise
  if (dot(b, c) < -EPS)     return +2;       // c--a--b on line
  if (norm(b) < norm(c)) return -2;       // a--b--c on line
  return 0;
}

P rotate(const P &p, double ang) {
  return p * P(cos(ang), sin(ang));
}

P projection(const L &l, const P &p) {
  double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
  return l[0] + t*(l[0]-l[1]);
}
P reflection(const L &l, const P &p) {
  return p + P(2,0) * (projection(l, p) - p);
}

double distanceLP(const L &l, const P &p) {
  return abs(p - projection(l, p));
}

bool intersectSP(const L &s, const P &p) {
  return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS; // triangle inequality
}
bool intersectLL(const L &l, const L &m) {
  return abs(cross(l[1]-l[0], m[1]-m[0])) > EPS || // non-parallel
         abs(cross(l[1]-l[0], m[0]-l[0])) < EPS;   // same line
}
bool intersectLS(const L &l, const L &s) {
  return cross(l[1]-l[0], s[0]-l[0])*       // s[0] is left of l
         cross(l[1]-l[0], s[1]-l[0]) < EPS; // s[1] is right of l
}
bool intersectLP(const L &l, const P &p) {
  return abs(cross(l[1]-p, l[0]-p)) < EPS;
}
bool intersectSS(const L &s, const L &t) {
  return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
         ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}
bool intersectSS2(const L &s, const L &t) {
  if (intersectSP(s,t[0]) || intersectSP(s,t[1]) ||
      intersectSP(t,s[0]) || intersectSP(t,s[1])) return 0;
  return intersectSS(s,t);
}
bool intersectHS(const L &h, const L &s) {
  if (intersectLP(h,s[0]) || intersectLP(h,s[1]) ||
      intersectLP(s,h[0]) || intersectLP(s,h[1])) return 0;
  if (intersectSS(h,s)) return 1;
  if (!intersectLS(h,s)) return 0;
  return (ccw(s[0],s[1],h[0]) == 1) ^ (cross(s[1]-s[0], h[1]-h[0]) > 0);
}

P crosspoint(const L &l, const L &m) {
  double A = cross(l[1] - l[0], m[1] - m[0]);
  double B = cross(l[1] - l[0], l[1] - m[0]);
  if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m[0] + B / A * (m[1] - m[0]);
}

bool EQ(double a, double b) {
  return abs(a-b) < EPS;
}
bool EQP(const P &a, const P &b) {
  return norm(a-b) < EPS*EPS;
}

#define index_of(ps, p) \
  distance(ps.begin(), lower_bound(ps.begin(), ps.end(), p))
Graph arrangement(const vector<L>& segs, vector<P>& pt) {
  vector< vector<double> > V(segs.size());
  for (int i = 0; i < segs.size(); ++i) {
    pt.push_back( segs[i][0] );
    pt.push_back( segs[i][1] );
    V[i].push_back(0);
    V[i].push_back(1);
    for (int j = i+1; j < segs.size(); ++j) {
      L a = segs[i], b = segs[j];
      if (intersectSS(a, b)) {
        double D = cross(b[1]-b[0], a[1]-a[0]);
        if (abs(D) < EPS) continue;
        double t = cross(b[1]-b[0], b[0]-a[0]) / D;
        double s = cross(a[0]-b[0], a[1]-a[0]) / D;
        V[i].push_back(t);
        V[j].push_back(s);
        pt.push_back( a[0]+(a[1]-a[0])*t );
      }
    }
  }
  sort(pt.begin(), pt.end());
  pt.erase(unique(pt.begin(), pt.end(), EQP), pt.end());

  Graph g(pt.size());
  for (int i = 0; i < V.size(); ++i) {
    vector<double>& cut = V[i];
    sort(cut.begin(), cut.end());
    cut.erase(unique(cut.begin(), cut.end(), EQ), cut.end());
    for (int j = 0; j+1 < cut.size(); ++j) {
      P a = segs[i][0] + (segs[i][1] - segs[i][0]) * cut[j];
      P b = segs[i][0] + (segs[i][1] - segs[i][0]) * cut[j+1];
      int src = index_of(pt, a), dst = index_of(pt, b);
      // cout << g.size() << " " << src << " " << dst << " " << abs(a-b) << endl;
      g[src].push_back( Edge(src, dst, abs(a-b)) );
      g[dst].push_back( Edge(dst, src, abs(a-b)) );
    }
  }
  return g;
}

int main() {
  int n;
  while(cin >> n, n) {
    vector<L> segs;
    REP(i,n) {
      P a, b;
      cin >> a.real() >> a.imag();
      cin >> b.real() >> b.imag();
      segs.push_back(L(a,b));
    }
    P s;
    cin >> s.real() >> s.imag();
    REP(i,n) {
      if (intersectSP(segs[i],s)) {
        segs.push_back(L(segs[i][0],s));
        segs.push_back(L(s,segs[i][1]));
      }
    }
    vector<P> pv;
    Graph g = arrangement(segs,pv);
    int sid = -1;
    REP(i,pv.size()) {
      if (abs(pv[i]-s) < EPS) sid = i;
    }
    assert(sid != -1);
    // REP(i,g.size()) {
    //   cout << i << endl;
    //   FOR(it, g[i]) {
    //     cout << it->dst << " " << it->weight << endl;
    //   }
    // }
    // cout << sid << endl;
    vector<double> dis = dijkstra(g,sid);
    double ans = 0;
    REP(i,g.size()) {
      FOR(it, g[i]) {
        int a = it->src;
        int b = it->dst;
        double x = (dis[b]-dis[a]+it->weight) / 2;
        chmax(ans, dis[a] + x);
      }
    }
    cout << setprecision(10) << fixed << ans << endl;
    // printf("%.10Lf\n", ans);
  }
}
accuracy: 1
time_ms: 2000
memory_kb: 11556
final_rank: 8

code_snippet: #include<iostream>
#include<stdio.h>
#include<complex>
#include<cfloat>
#include<cassert>
#include<cmath>
#include<vector>
#include<queue>
#include<algorithm>

using namespace std;



#define EPS (1e-8)
#define equals(a, b) (abs((a) - (b)) < EPS )

class Point{
    public:
    double x, y;
    
    Point ( double x = 0, double y = 0): x(x), y(y){}
    
    Point operator + ( Point p ){
	return Point(x + p.x, y + p.y);
    }

    Point operator - ( Point p ){
	return Point(x - p.x, y - p.y);
    }

    Point operator * ( double a ){
	return Point(a*x, a*y);
    }

    double absolute() { return sqrt(norm());}
    double norm() { return x*x + y*y; }

    bool operator < ( const Point &p ) const{
	return x != p.x ? x < p.x : y < p.y;
    }

    bool operator == ( const Point &p ) const {
	return abs(x-p.x) < EPS && abs(y-p.y) < EPS;
    }
};

typedef Point Vector;

class Segment{
    public:
    Point source, target;
    Segment(Point s = Point(), Point t = Point()): source(s), target(t){}
};

double norm( Vector a ){
    return a.x*a.x + a.y*a.y;
}

double absolute( Vector a ){
    return sqrt(norm(a));
}

double getDistance(Vector a, Vector b){
    return absolute(a - b); 
}

// dot product
double dot(Vector a, Vector b){
    return a.x*b.x + a.y*b.y;
}

// cross product
double cross(Vector a, Vector b){
    return a.x*b.y - a.y*b.x;
}

Point project( Segment s, Point p ){
    Vector base = s.target - s.source;
    double t = dot(p - s.source, base)/norm(base);
    return s.source + (base)*t;
}

Point reflect( Segment s, Point p ){
    return p + (project(s, p) - p)*2.0;
}

// verified by uoa2062
bool isOnSegment( Point a, Point b, Point c){
    if ( a == c || b == c ) return true;
    return (absolute(a-c) + absolute(c-b) < absolute(a-b) + EPS );
}

bool isOrthogonal( Vector a, Vector b ){
     return equals( dot(a, b), 0.0 );
}

bool isOrthogonal( Point a1, Point a2, Point b1, Point b2 ){
    return isOrthogonal( a1 - a2, b1 - b2 );
}

bool isOrthogonal( Segment s1, Segment s2 ){
    return equals( dot(s1.target - s1.source, s2.target - s2.source), 0.0 );
}

bool isParallel( Vector a, Vector b ){
    return equals( cross(a, b), 0.0 );
}

bool isParallel( Point a1, Point a2, Point b1, Point b2){
    return isParallel( a1 - a2, b1 - b2 );
}

bool isParallel( Segment s1, Segment s2 ){
    return equals( cross(s1.target - s1.source, s2.target - s2.source), 0.0 );
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

int ccw( Point p0, Point p1, Point p2 ){
    Vector a = p1 - p0;
    Vector b = p2 - p0;
    if ( cross(a, b) > EPS ) return COUNTER_CLOCKWISE;
    if ( cross(a, b) < -EPS ) return CLOCKWISE;
    if ( dot(a, b) < -EPS ) return ONLINE_BACK;
    if ( norm(a) < norm(b) ) return ONLINE_FRONT;
    return ON_SEGMENT;
}

// intersect Segment p1-p2 and Segment p3-p4 ?
bool isIntersect(Point p1, Point p2, Point p3, Point p4){
    return ( ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 &&
	     ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0 );
}

// intersect Segment s1 and Segment s2 ?
// verified by 920, 833, 866, uoa2062
bool isIntersect(Segment s1, Segment s2){
    return isIntersect(s1.source, s1.target, s2.source, s2.target);
}

// verified by 920, 833, uoa2062
Point getCrossPoint(Segment s1, Segment s2){
    assert( isIntersect(s1, s2) );
    Vector base = s2.target - s2.source;
    double d1 = absolute(cross(base, s1.source - s2.source));
    double d2 = absolute(cross(base, s1.target - s2.source));
    double t = d1/(d1 + d2);
    return s1.source + (s1.target - s1.source)*t;
}


#define MAX 2000
#define NMAX 80000
#define LIMIT FLT_MAX

class Edge{
    public:
    int target;
    double dist;
    Edge(){}
    Edge(int target, double dist): target(target), dist(double(dist)){}
};

class Graph{
    public:
    vector<Edge> adjList[NMAX];
    int start;

    Graph(){
	for ( int i = 0; i < NMAX; i++ ) adjList[i].clear();
    }
    
    void connect( int i, int j, double d ){
	adjList[i].push_back(Edge(j, d));
	adjList[j].push_back(Edge(i, d));
    }
};

class QNode{
    public:
    int index;
    double cost;
    QNode(){}
    QNode( int index, double cost ): index(index), cost(cost){}
    
    bool operator < ( const QNode &q ) const { return cost > q.cost; }
};

class Node{
    public:
    Point p;
    int id;
    Node(){}
    Node( Point p, int id): p(p), id(id){}
    bool operator < ( const Node &n) const {
	return p < n.p;
    }
};

int nnode;
Point SP[NMAX];

int getIndex( Point p ){
    SP[nnode++] = p;
    return nnode-1;
}

void makeGraph(Graph &g, Segment S[MAX], int N, Point s ){
    Segment base, target;
    Node L[NMAX];
    int beg, p = 0;
    bool startSet = false;
    nnode = 0;
    for ( int b = 0; b < N; b++ ){
	base = S[b];
	beg = p;

	if ( !startSet && isOnSegment(base.source, base.target, s) ){
	    L[p++] = Node(s, getIndex(s));
	    startSet = true;
	}

	L[p++] = Node(base.source, getIndex(base.source));
	L[p++] = Node(base.target, getIndex(base.target));

	for ( int t = 0; t < N; t++ ){
	    if ( t == b ) continue;
	    target = S[t];
	    if ( !isIntersect(base, target) ) continue;
	    Point cp = getCrossPoint(base, target);
	    L[p++] = Node(cp, getIndex(cp));
	}

	sort(L + beg, L + p );

	for ( int i = beg; i < p-1; i++ ){
	    g.connect(L[i].id, L[i+1].id, getDistance(L[i].p, L[i+1].p));
	}
    }

    sort( L, L + p );

    for ( int i = 0; i < p-1; i++ ){
      //	if ( eq(L[i].p, L[i+1].p) ) 
      if ( L[i].p ==  L[i+1].p ) 
	    g.connect( L[i].id, L[i+1].id, 0.0);
      //	if ( eq(L[i].p, s) ) g.start = L[i].id;
      if ( L[i].p == s ) g.start = L[i].id;
    }

}

double dijkstra(Graph g){
    bool visited[NMAX];
    double D[NMAX];
    priority_queue<QNode> PQ;
    
    for ( int i = 0; i < nnode; i++ ) {
	visited[i] = false;
	D[i] = LIMIT;
    }

    for ( int i = 0; i < g.adjList[g.start].size(); i++ ){
	Edge v = g.adjList[g.start][i];
	PQ.push(QNode(v.target, v.dist) );
	D[v.target] = v.dist;
    }

    visited[g.start] = true;
    D[g.start] = 0.0;

    QNode u;

    while( !PQ.empty() ){
	u = PQ.top(); PQ.pop();
	if ( visited[u.index] ) continue;
	visited[u.index] = true;
	for ( int i = 0; i < g.adjList[u.index].size(); i++ ){
	    Edge v = g.adjList[u.index][i];
	    if ( visited[v.target] ) continue;
	    if ( D[u.index] + v.dist < D[v.target] ){
		D[v.target] = D[u.index] + v.dist;
		PQ.push(QNode(v.target, D[v.target]));
	    }
	}
    }

    double mdist = 0.0;

    for ( int i = 0; i < nnode; i++ ){
	mdist = max(mdist, D[i] );
	for ( int k = 0; k < g.adjList[i].size(); k++ ){
	    int j = g.adjList[i][k].target;
	    double d = getDistance(SP[i], SP[j]);
	    mdist = max(mdist, (double)(min(D[i], D[j]) + (d - abs(D[i]-D[j]))/2.0));
	}
    }
    return mdist;
}

int main(){
    int N;
    Segment S[MAX];

    while( cin >> N && N ){
	Point p1, p2;
	for ( int i = 0; i < N; i++ ){
	    cin >> p1.x; cin >> p1.y;
	    cin >> p2.x; cin >> p2.y;
	    S[i] = Segment(p1, p2);
	}
	cin >> p1.x; cin >> p1.y;
	Graph g;
	makeGraph(g, S, N, p1);
	printf("%.5lf\n", dijkstra(g));
    }

    return 0;
}

/**
daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaadaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaa


*/
accuracy: 1
time_ms: 1570
memory_kb: 12000
final_rank: 6