#include <queue>
#include <cmath>
#include <vector>
#include <cstdio>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100 + 10;
const long double INF = 1e9;
const long double EPS = 1e-8;
const int OFFSET = 100000;

int sign(long double x)
{
	return x < -EPS ? -1 : x > EPS;
}

long double Sqr(long double x){
	return x*x;
}

struct Point
{
	long double x, y;
	Point() {}
	Point(long double x, long double y) : x(x), y(y) {}
	Point operator + (const Point &that) const {
		return Point(x + that.x, y + that.y);
	}
	Point operator - (const Point &that) const {
		return Point(x - that.x, y - that.y);
	}
	Point operator * (const long double &that) const {
		return Point(x * that, y * that);
	}
	Point operator / (const long double &that) const {
		return Point(x / that, y / that);
	}
	void read() {
		cin >> x >> y;
	}
	long double dot(const Point &that) const {
		return x * that.x + y * that.y;
	}
	long double distTo(const Point &that) const {
		return sqrt(Sqr(x - that.x) + Sqr(y - that.y));
	}
	Point rot90() const {
		return Point(-y, x);
	}
};

#define cross(p1,p2,p3) ((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))
#define crossOp(p1,p2,p3) sign(cross(p1,p2,p3))

int n;
Point bomb;
vector<vector<Point> > polygon;
long double dist[N][N];
bool alive[N][N];
bool in[N][N];

inline bool isIntersect(Point p1, Point p2, Point q1, Point q2)
{
	return crossOp(p1, p2, q1) * crossOp(p1, p2, q2) <= 0 && crossOp(q1, q2, p1) * crossOp(q1, q2, p2) < 0;
}

inline Point isSS(Point p1, Point p2, Point q1, Point q2)
{
	long double a1 = cross(q1, q2, p1), a2 = -cross(q1, q2, p2);
	return (p1 * a2 + p2 * a1) / (a1 + a2);
}

bool inPolygon(vector<Point> &vec, Point s)
{
	int n = vec.size();
	for(int i = 0; i < n; ++ i) {
		if (crossOp(vec[i], vec[(i + 1) % n], s) == 0 && sign((vec[i] - s).dot(vec[(i + 1) % n] - s)) <= 0)
			return false;
	}
	int flag = true;
	Point t;
	for( ; flag; ) {
		t = Point(253514,999983);
		flag = false;
		for(int i = 0; i < n; ++ i) {
			if (crossOp(s, t, vec[i]) == 0) {
				flag = true;
				break;
			}
		}
	}
	int ret = 0;
	for(int i = 0; i < n; ++ i) {
		if (isIntersect(s, t, vec[i], vec[(i + 1) % n]))
			++ ret;
	}
	return ret & 1;
}

inline bool inPolygon(Point s)
{
	for(int i = 1; i <= n; ++ i) {
		if (inPolygon(polygon[i], s)) {
			return true;
		}
	}
	return false;
}

bool isAccess(Point s, Point t)
{
	for(int i = 1; i <= n; ++ i) {
		for(int j = 0; j < polygon[i].size(); ++ j) {
			if (isIntersect(s, t, polygon[i][j], polygon[i][(j + 1) % polygon[i].size()])) {
				return false;
			}
		}
	}
	if (inPolygon((s + t) * 0.5)) {
		return false;
	}
	return true;
}

void solve()
{
	bomb.read();
	polygon.clear();
	polygon.push_back(vector<Point>(1, Point(0, 0)));
	for(int i = 0; i < n; ++ i) {
		int cnt;
		cin >> cnt;
		vector<Point> vec;
		for(int j = 0; j < cnt; ++ j) {
			Point cur;
			cur.read();
			vec.push_back(cur);
		}
		polygon.push_back(vec);
	}
	for(int i = 0; i < polygon.size(); ++ i) {
		for(int j = 0; j < polygon[i].size(); ++ j) {
			alive[i][j] = false;
		}
		for(int j = 0; j < polygon[i].size(); ++ j) {
			if (crossOp(bomb, polygon[i][j], polygon[i][(j + 1) % polygon[i].size()]) > 0)
				alive[i][j] = alive[i][(j + 1) % polygon[i].size()] = true;
		}
	}
	
	for(int i = 0; i < N; ++ i) {
		for(int j = 0; j < N; ++ j) {
			dist[i][j] = INF;
			in[i][j] = false;
		}
	}
	dist[0][0] = 0;
	priority_queue<pair<long double, pair<int, int> > > que;
	que.push(make_pair(0,  make_pair(0, 0)));

	if (! isAccess(Point(0, 0), bomb)) {
		printf("%.12f\n", 0.0);
		return;
	}
	long double cut=1e30;
	for( ; que.size(); ) {
		int a = que.top().second.first;
		int b = que.top().second.second;

		if (a == -1 || alive[a][b]) {
			printf("%.12f\n", (double)-que.top().first);
			return;
		}
		que.pop();
		if (in[a][b]) continue;
		in[a][b] = true;

		for(int c = 1; c < polygon.size(); ++ c) {
			for(int d = 0; d < polygon[c].size(); ++ d) {
				if (dist[c][d] > dist[a][b] + polygon[a][b].distTo(polygon[c][d]) && isAccess(polygon[a][b], polygon[c][d])) {
					dist[c][d] = dist[a][b] + polygon[a][b].distTo(polygon[c][d]);
					que.push(make_pair(-dist[c][d], make_pair(c, d)));
				}
				if (alive[c][d] && isAccess(bomb,polygon[c][d])) {
					Point foot = isSS(bomb, polygon[c][d], polygon[a][b], polygon[a][b] + (polygon[c][d] - bomb).rot90());
					if (foot.distTo(bomb) >= polygon[c][d].distTo(bomb) && isAccess(foot, polygon[a][b])) {
						que.push(make_pair(-dist[a][b] - foot.distTo(polygon[a][b]), make_pair(-1, -1)));
					}
				}
			}
		}
	}
}

int main()
{
	ios::sync_with_stdio(false);
	for( ; cin >> n && n; ) {
		solve();
	}
	return 0;
}

Measured memory_bytes: 1556