#include<complex>
#include<vector>
#include<iostream>
#include<stack>
#include<cmath>
#include<queue>
#include<fstream>
#include<functional>
#include<cstdio>
#include<set>
#include<cassert>

enum ENUM_CCW{FRONT=0x01,RIGHT=0x02,BACK=0x04,LEFT=0x08,OVER=0x10};

#define sc second
#define fr first

using namespace std;

typedef double elem;
typedef complex<elem> point, vec;
typedef pair<point, point> line, hline, seg, pp;

const double infty = 1e40;
const double eps = 1.0e-8;
const double pi = acos(-1.0);

inline bool eq(elem a, elem b){ return abs(a-b) < eps; }
inline bool far(const point &a, const point &b){ return abs(b-a)>0; }
inline bool near(const point &a, const point &b){ return abs(b-a)<=0; }
inline elem dot(const vec &a, const vec &b){ return (a.real() * b.real() + a.imag() * b.imag() ); }
inline elem cross(const vec &a, const vec &b){ return ( a.real() * b.imag() - a.imag() * b.real() ); }
inline vec uvec(const vec &a){ return a / abs(a); }
inline vec nmr(const vec &a){ return a * vec(0,-1); }
inline vec unmr(const vec &a){ return uvec( nmr(a) ); }
inline elem dist_l(const line &l, const point &x){ return abs(cross(l.sc-l.fr,x-l.fr)) / abs(l.sc-l.fr); }
inline int ccw(const point &a, point b, point x){
  b -= a;
  x -= a;
  if( eq(cross(b,x),0.0) && dot(b,x) < 0 ) return BACK;
  if( eq(cross(b,x),0.0) && abs(b) < abs(x) ) return FRONT;
  if( eq(cross(b,x),0.0) ) return OVER;
  if( cross(b,x) > 0 ) return LEFT;
  if( cross(b,x) < 0 ) return RIGHT;
}
inline bool intersectedSS(const seg &a, const seg &b)
{
  int cwaf=ccw(a.fr,a.sc,b.fr);
  int cwbf=ccw(b.fr,b.sc,a.fr);
  int cwas=ccw(a.fr,a.sc,b.sc);
  int cwbs=ccw(b.fr,b.sc,a.sc);
  if( cwaf==OVER || cwas==OVER || cwbf==OVER || cwbs==OVER ) return true;
  return ( cwaf | cwas ) == (LEFT|RIGHT) && ( cwbf | cwbs ) == (LEFT|RIGHT);
}
inline bool intersectedLL(const line &a, const line &b){ return !eq( cross(a.sc-a.fr,b.sc-b.fr), 0.0 ); }
inline point intersectionSS(const seg &a, const seg &b)
{
  elem d1 = dist_l(b,a.fr);
  elem d2 = dist_l(b,a.sc);
  return a.fr + ( d1 / (d1 + d2 ) ) * (a.sc-a.fr);
}
inline point intersectionLL(const line &a, const line &b)
{
  vec va = a.sc - a.fr;
  vec vb = b.sc - b.fr;
  return a.fr + va * ( cross(vb, b.fr - a.fr) / cross(vb,va) );
}
inline bool intersectionLL(const line &a, const line &b, point &ret){
  return intersectedLL( a, b ) ? ret = intersectionLL( a, b ), true : false;
}
inline bool intersectionLH(const line &a, const hline &b, point &ret){
  point tmp;
  return intersectionLL(a,b,tmp) ? ( ccw(b.fr,b.sc,tmp)&(OVER|FRONT) ? ret=tmp, true : false ) : false;
}
inline bool intersectionLS(const line &l, const seg &s, point &ret){
  point tmp;
  return intersectionLL(l,s,tmp) ? ( ccw(s.fr,s.sc,tmp)&OVER ? ret=tmp, true : false ) : false;
}
inline bool intersectionHH(const hline &a, const hline &b, point &ret){
  point tmp;
  return intersectionLL(a,b,tmp) ? ( ccw(a.fr,a.sc,tmp)&(OVER|FRONT)&&ccw(b.fr,b.sc,tmp)&(OVER|FRONT) ? ret = tmp, true : false ) : false;
}
inline bool intersectionHS(const hline &a, const seg &s, point &ret){
  point tmp;
  return intersectionLS(a,s,tmp) ? ( ccw(a.fr,a.sc,tmp)&(OVER|FRONT) ? ret = tmp, true : false ) : false;
}
inline bool intersectionSS(const seg &a, const seg &b, point &ret){
  return intersectedSS(a,b) ? ret = intersectionSS(a,b), true : false;
}

bool inSimple(const point &x, int n, point p[])
{
  int cnt=0;
  for(int i = 0; i < n; ++i){
    point a=p[i]-x,b=p[(i+1)%n]-x;
    if(b.imag()>a.imag())swap(a,b);
    int cw=ccw(a,b,point(0,0));
    if(cw==LEFT&&0<=a.imag()&&b.imag()<0)++cnt;
    if(cw==OVER)return false;
  }
  if(cnt&1)return true;
  else return false;
}

struct State{
  int n;
  elem cost;
  State(int n, elem cost):n(n),cost(cost){}
  State(){}
  bool operator<(const State &t)const{
    return cost > t.cost;
  }
};

#define MAXN 512

int N;
point B[MAXN][128];
int nB[MAXN];
int nG;
point G[MAXN];
int GSafe[MAXN];
int nGoal;
point Goal[2*MAXN];

bool isConnected( const point &a, const point &b){
  point x=(a+b)/(elem)2.0;
  for(int i = 0; i < N; ++i){
    //    if(inSimple(x,nB[i],B[i]))return false;
    int cnt=0;
    for(int j = 0; j < nB[i]; ++j){
      point p=B[i][j];
      point np=B[i][(1+j)%nB[i]];
      point tmp;
      if(intersectionSS(seg(a,b),seg(p,np),tmp)){
	if(far(tmp,a)&&far(tmp,b))return false;
      }
      point a=B[i][j]-x,b=B[i][(j+1)%nB[i]]-x;
      if(b.imag()>a.imag())swap(a,b);
      int cw=ccw(a,b,point(0,0));
      if(cw==LEFT&&0<=a.imag()&&b.imag()<0)++cnt;
      if(cw==OVER){cnt=0;break;}
    }
    if(cnt&1)return false;
  }
  return true;
}

elem solve(){
  elem ret = infty;
  elem A[nG];
  bool visited[nG];
  bool adj[nG][nG];
  priority_queue<State> Q;
  State init(0,0.0);
  Q.push(init);

  for(int i = 0; i < nG; ++i){
    visited[i] = false;
    A[i] = infty;
    for(int j = 0; j < nG; ++j){
      adj[i][j]=false;
    }
  }
  
  A[0] = 0.0;
  while(!Q.empty()){
    State nst = Q.top(); Q.pop();
    if(visited[nst.n])continue;
    visited[nst.n]=true;
    point np = G[nst.n];
    if(GSafe[nst.n]){
      ret=min(ret,nst.cost);
      break;
    }

    for(int i = 0; i < nGoal; ++i){
      if( isConnected(np,Goal[i]) ){
	ret = min(ret,nst.cost+abs(Goal[i]-np));
      }
    }

    for(int i = 1; i < nG; ++i){
      if( nst.n == i ) continue;
    retry:;
      if( adj[nst.n][i] ){
	elem nxcost = nst.cost + abs(G[i]-np);
	if( A[i] > nxcost ){
	  A[i]=nxcost;
	  if(!visited[i]){
	    Q.push(State(i,nxcost));
	  }
	}
      }else{
	if( isConnected(np,G[i]) ){
	  adj[nst.n][i]=adj[i][nst.n]=true;
	  goto retry;
	}
      }
    }
  }
  return ret;
}

bool eqseg(seg a, seg b){
  return
    (near(a.fr,b.fr)&&near(a.sc,b.sc))||
    (near(a.fr,b.sc)&&near(a.sc,b.fr));
}

int main(){
  point p(0,0);
  point s;

  while(true){
    // input
    cin >> N;
    if(N==0)break;
    elem bx,by;
    cin >> bx >> by;
    point bomb(bx,by);
    point alice(0,0);

    for(int i = 0; i < N; ++i){
      int m;
      cin >> m;
      nB[i]=m;
      for(int j = 0; j < m; ++j){
	elem x,y;
	cin >> x >> y;
	B[i][j]=point(x,y);
      }
    }

    for(int i = 0; i < N; ++i){
      for(int j = 0; j < nB[i]; ++j){
	point p = B[i][j];
	point nexp = B[i][(j+1)%nB[i]];
      }
    }
    
    // graph points
    nG=1;
    nGoal=0;
    G[0]=alice;
    GSafe[0]=0;
    for(int i = 0; i < N; ++i){
      for(int j = 0; j < nB[i]; ++j){

	point p = B[i][j];
	// vertex
	G[nG]=p;
	{
	  // is safe vertex ?
	  bool safe = false;
	  point prep = B[i][(j-1+nB[i])%nB[i]];
	  point nexp = B[i][(j+1)%nB[i]];
	  point cp = (p + prep) / (elem)2.0;
	  point cx = (p + nexp) / (elem)2.0;
	  hline lcp(bomb,cp);
	  hline lcx(bomb,cx);
	  
	  point tmp;
	  
	  // there is a segment that guards alice from bomb
	  if( intersectionSS(seg(bomb,alice),seg(p,prep),tmp)&&
	      far(tmp,bomb)&&far(tmp,alice)){
	    GSafe[0]=1;
	  }

	  for(int k = 0; k < N; ++k){
	    for(int m = 0; m < nB[k]; ++m){
	      seg s(B[k][m],B[k][(m+1)%nB[k]]);
	      if( eqseg(lcp,s) ) continue;
	      point is;
	      if( intersectionSS( lcp,s,is ) && far( is, cp ) && abs(is-bomb)<abs(cp-bomb) ){
		if( ccw(p,prep,alice)==OVER ){
		  GSafe[0]=1;
		}
		safe = true;
	      }
	      if( intersectionSS( lcx,s,is ) && far( is, cx ) && abs(is-bomb)<abs(cx-bomb) ){
		if( ccw(p,nexp,alice)==OVER ){
		  GSafe[0]=1;
		}
		safe = true;
	      }
	    }
	    if(safe)break;
	  }
	  if(safe){
	    GSafe[nG]=1;
	  }else{
	    GSafe[nG]=0;
	  }
	}
	++nG;
	
	
	// vertical line
	if(far(bomb,p)){
	  hline l(bomb,p);
	  line al(alice,alice+unmr(bomb-p));
	  point is;
	  if( intersectionLH(al,l,is)){
	    bool skip=false;
	    for(int k = 0; k < N; ++k){
	      if(inSimple(is,nB[k],B[k]))skip=true;
	      for(int m = 0; m < nB[k]; ++m){
		if( near(is,B[k][m])||near(is,alice) ){
		  skip=true;
		}
	      }
	    }
	    if(!skip&&abs(is-bomb)>abs(p-bomb)){
	      Goal[nGoal]=is;
	      nGoal++;
	    }
	  }
	  
	  // half line and polygon
	  for(int k = 0; k < N; ++k){
	    for(int m = 0; m < nB[k]; ++m){
	      seg s(B[k][m],B[k][(m+1)%nB[k]]);
	      if( intersectionHS( l,s,is ) ){
		if(far(is,p)&&far(is,s.first)&&far(is,s.second)&&abs(is-bomb)>abs(p-bomb)){
		  Goal[nGoal]=is;
		  nGoal++;
		}
	      }
	    }
	  }
	}
      }
    }

    printf("%.12lf\n", solve());
  }
  return 0;
}

Measured memory_bytes: 2324