#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <ctime>
#include <queue>
#include <stack>
#include <algorithm>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
#include <deque>
#include <complex>
#include <string>
#include <iomanip>
#include <sstream>
#include <bitset>
#include <valarray>
#include <unordered_map>
#include <iterator>
#include <assert.h>
using namespace std;
typedef long long int ll;
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;

#define REP(i,x) for(int i=0;i<(int)(x);i++)
#define REPS(i,x) for(int i=1;i<=(int)(x);i++)
#define RREP(i,x) for(int i=((int)(x)-1);i>=0;i--)
#define RREPS(i,x) for(int i=((int)(x));i>0;i--)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();i++)
#define RFOR(i,c) for(__typeof((c).rbegin())i=(c).rbegin();i!=(c).rend();i++)
#define ALL(container) (container).begin(), (container).end()
#define RALL(container) (container).rbegin(), (container).rend()
#define SZ(container) ((int)container.size())
#define mp(a,b) make_pair(a, b)
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );

template<class T> bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T> bool chmin(T &a, const T &b) { if (a>b) { a=b; return 1; } return 0; }
template<class T> ostream& operator<<(ostream &os, const vector<T> &t) {
os<<"["; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"]"; return os;
}
template<class T> ostream& operator<<(ostream &os, const set<T> &t) {
os<<"{"; FOR(it,t) {if(it!=t.begin()) os<<","; os<<*it;} os<<"}"; return os;
}
template<class S, class T> ostream& operator<<(ostream &os, const pair<S,T> &t) { return os<<"("<<t.first<<","<<t.second<<")";}
template<class S, class T> pair<S,T> operator+(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first+t.first, s.second+t.second);}
template<class S, class T> pair<S,T> operator-(const pair<S,T> &s, const pair<S,T> &t){ return pair<S,T>(s.first-t.first, s.second-t.second);}

namespace geom{
#define X real()
#define Y imag()
#define at(i) ((*this)[i])
#define SELF (*this)
	enum {TRUE = 1, FALSE = 0, BORDER = -1};
	typedef int BOOL;
	typedef long double R;
	const R INF = 1e8;
	R EPS = 1e-6;
	const R PI = 3.1415926535897932384626;
	inline int sig(const R &x) { return (abs(x) < EPS ? 0 : x > 0 ? 1 : -1); }
	inline BOOL less(const R &x, const R &y) {return sig(x-y) ? x < y : BORDER;}
	typedef complex<R> P;
	inline R norm(const P &p){return p.X*p.X+p.Y*p.Y;}
	inline R inp(const P& a, const P& b){return (conj(a)*b).X;}
	inline R outp(const P& a, const P& b){return (conj(a)*b).Y;}
	inline P unit(const P& p){return p/abs(p);}
	inline P proj(const P &s, const P &t){return t*inp(s, t)/norm(t);}
	inline int ccw(const P &s, const P &t, const P &p, int adv=0){
		int res = sig(outp(t-s, p-s));
		if(res || !adv) return res;
		if(sig(inp(t-s, p-s)) < 0) return -2;	// p-s-t
		if(sig(inp(s-t, p-t)) < 0) return 2;	// s-t-p
		return 0;								// s-p-t
	}
	
	
	struct L : public vector<P>{	// line
		L(const P &p1, const P &p2){this->push_back(p1);this->push_back(p2);}
		L(){}
		P dir()const {return at(1) - at(0);}
		BOOL online(const P &p)const {return !sig(outp(p-at(0), dir()));}
	};
	struct S : public L{	// segment
		S(const P &p1, const P &p2):L(p1, p2){}
		S(){}
		BOOL online(const P &p)const {
			if(!sig(norm(p - at(0))) || !sig(norm(p - at(1)))) return BORDER;
			// テ・ツコツァテヲツィツ凖」ツ?ョテ、ツコツ古、ツケツ療」ツ?ィEPSテ」ツ?ョテ・ツキツョテ」ツ?古・ツ、ツァテ」ツ?催」ツ?凖」ツ?偲」ツ?ェテ」ツ??」ツつ暗」ツ??」ツ?ォテヲツウツィテヲツ??
			return !sig(outp(p-at(0), dir())) && inp(p-at(0), dir()) > EPS && inp(p-at(1), -dir()) > -EPS;
			//return !sig(abs(at(0)-p) + abs(at(1) - p) - abs(at(0) - at(1)));
		}
	};
	P crosspoint(const L &l, const L &m);
	struct G : public vector<P>{
		G(size_type size=0):vector(size){}
		S edge(int i)const {return S(at(i), at(i+1 == size() ? 0 : i+1));}
	};

	inline P proj(const P &s, const L &t){return t[0] + proj(s-t[0], t[1]-t[0]);}
	inline P reflect(const P &s, const L &t){return (R)2.*proj(s, t) - s;}
	inline S reflect(const S &s, const L &t){return S(reflect(s[0], t), reflect(s[1], t));}
	BOOL intersect(const S &s, const S &t){
		const int p = ccw(t[0], t[1], s[0], 1) * ccw(t[0], t[1], s[1], 1);
		const int q = ccw(s[0], s[1], t[0], 1) * ccw(s[0], s[1], t[1], 1);
		return (p>0||q>0) ? FALSE : (!p||!q) ? BORDER : TRUE;
	}
	BOOL intersect(const S &s, const L &l){
		if(l.online(s[0]) || l.online(s[1])) return BORDER;
		return (sig(outp(l.dir(), s[0]-l[0])) * sig(outp(l.dir(), s[1]-l[0])) <= 0);
	}
	R dist2(const L &l, const P &p){return norm(outp(l.dir(), p - l[0])) / norm(l.dir());}
	R dist2(const S &s, const P &p){
		if(inp(p-s[0],  s.dir()) < EPS) return norm(p - s[0]);
		if(inp(p-s[1], -s.dir()) < EPS) return norm(p - s[1]);
		return dist2((const L &)s, p);
	}
	R dist2(const S &s, const L &l){
		return intersect(s, l) ? .0 : min(dist2(l, s[0]), dist2(l, s[1]));
	}
	R dist2(const S &s, const S &t){
		return intersect(s, t) ? .0 : min(min(dist2(s, t[0]), dist2(t, s[0])), 
									   	  min(dist2(s, t[1]), dist2(t, s[1])));
	}
	template <class T> R dist2(const G &g, const T& t){ // todo: テ・ツ??ゥツδィテ」ツ?ォテ・ツョツ古・ツ?ィテ」ツ?ォテ・ツ青ォテ」ツ?セテ」ツつ古」ツつ凝・ツ?エテ・ツ青?
		R res = INF;
		REP(i, g.size()) res = min(res, dist2(g.edge(i), t));
		return res;
	}
	template<class S, class T> R dist(const S& s, const T& t){return sqrt(dist2(s, t));}
	inline P crosspoint(const L &l, const L &m){
		R A = outp(l.dir(), m.dir()), B = outp(l.dir(), l[1] - m[0]);
		if(!sig(abs(A)) && !sig(abs(B))) return m[0]; // same line
		if(abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
		return m[0] + B / A * (m[1] - m[0]);
	}

#undef SELF
#undef at
}

using namespace geom;

int f = 0;
namespace std{
	bool operator<(const P &a, const P &b){return sig(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;}
	istream& operator>>(istream &is, P &p){R x,y;is>>x>>y;p=P(x, y);return is;}
}
int n;

int main(int argc, char *argv[]){
	ios::sync_with_stdio(false);
	int T = 1;
	while(cin >> n, n){
		P p;
		cin >> p;
		vector<G> g(n);
		REP(i, n){
			int x;
			cin >> x;
			g[i].resize(x);
			REP(j, x){
				cin >> g[i][j];
				g[i][j] -= p;
			}
		}
		p = -p;
		if([&](){
			REP(i, n)REP(j, g[i].size()){
				if(intersect(g[i].edge(j), S(0, p)) == TRUE) return 1;
			}
			return 0;
		}()){
			printf("%.10f\n", .0);
			continue;
		}
		
		vector<S> acc;
		REP(i, n)REP(j, g[i].size()){
			L s(0, unit(g[i][j]));
			if(ccw(0, s[1], g[i][(j+1)%g[i].size()]) != ccw(0, s[1], g[i][(j-1+g[i].size())%g[i].size()])) continue;
			R from = abs(g[i][j]), to = 20000;
			REP(ii, n)REP(jj, g[ii].size()){
				S t = g[ii].edge(jj);
				if(!sig(outp(s.dir(), t.dir())) || intersect(t, s) != TRUE) continue;
				P p = crosspoint(s, t);
				if(inp(s.dir(), p) > 0){
					to = min(to, abs(p));
				}
			}
			if(from < to) acc.emplace_back(s[1]*from, s[1]*to);
		}
		auto cango = [&](const P &s, const P &t){
			const S root(s, t);
			REP(i, n)REP(j, g[i].size()){
				const S edge = g[i].edge(j);
				if(sig(outp(root.dir(), edge.dir())) && intersect(root, edge) == TRUE) return 0;
			}
			return 1;
		};
		
		struct State{
			int x, y;
			R cost;
			State (int x, int y, R cost)
				:x(x), y(y), cost(cost){}
			bool operator<(const State &opp) const{
				return cost > opp.cost;
			}
		};
		vector<vector<R>> visited(n, vector<R>(101, INF));
		priority_queue<State> pq;
		pq.emplace(-1, -1, 0);
		R ans = INF;
		while(!pq.empty()){
			State s = pq.top(); pq.pop();
			P q = (s.x == -1) ? p : g[s.x][s.y];
			if(s.cost > ans) break;
			if(s.x >= 0 && visited[s.x][s.y] < s.cost - EPS) continue;
			FOR(it, acc){
				P pr = proj(q, *it);
				if(inp(pr - (*it)[0], it->dir()) < EPS) pr = (*it)[0];
				else if(inp(pr - (*it)[1], -it->dir()) < EPS) pr = (*it)[1];
				if(s.cost + abs(q - pr) < ans - EPS && cango(q, pr)){
					ans = s.cost + abs(q - pr);
				}
			}
			REP(i, n)REP(j, g[i].size()){
				R c = s.cost + abs(g[i][j] - q);
				if(c+EPS > visited[i][j]) continue;
				if(cango(q, g[i][j])){
					visited[i][j] = c;
					pq.emplace(i, j, c);
				}
			}
		}
		printf("%.10f\n", (double)ans);
	}
	return 0;
}

Measured memory_bytes: 1488