#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

inline int sign(double x, double eps = 1e-8) {
	return x < -eps ? -1 : x > eps;
}

struct Point {
	double x, y;

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

	void in() {
		scanf("%lf%lf", &x, &y);
	}

	Point operator + (const Point &a) const {
		return Point(x + a.x, y + a.y);
	}

	Point operator - (const Point &a) const {
		return Point(x - a.x, y - a.y);
	}

	Point operator * (const double &k) const {
		return Point(x * k, y * k);
	}

	Point operator / (const double &k) const {
		return Point(x / k, y / k);
	}

	double len() const {
		return sqrt(x * x + y * y);
	}

	double len2() const {
		return x * x + y * y;
	}
};

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

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

struct Segment {
	Point a, b;

	Segment(Point a = Point(0, 0), Point b = Point(0, 0)) : a(a), b(b) {}

	Point mid() const {
		return (a + b) / 2;
	}
};

bool parallel(const Segment &l0, const Segment &l1) {
	return sign(det(l0.b - l0.a, l1.b - l1.a)) == 0;
}

Point intersect(const Segment &l0, const Segment &l1) {
	double s0 = det(l1.a - l0.a, l0.b - l0.a),
		   s1 = det(l1.b - l0.a, l0.b - l0.a);
	return (l1.b * s0 - l1.a * s1) / (s0 - s1);
}

bool onLine(const Segment &l0, const Point &p) {
	return sign(det(p - l0.a, l0.b - l0.a)) == 0;
}

bool inSeg(const Segment &l0, const Point &p) {
	return sign(dot(p - l0.a, l0.b - l0.a)) > 0 && sign(dot(p - l0.b, l0.a - l0.b)) > 0;
}

bool onSeg(const Segment &l0, const Point &p) {
	return sign(dot(p - l0.a, l0.b - l0.a)) >= 0 && sign(dot(p - l0.b, l0.a - l0.b)) >= 0;
}

Point project(const Segment &l, const Point &p) {
	return l.a + (l.b - l.a) * dot(p - l.a, l.b - l.a) / (l.b - l.a).len2();
}

bool inside(const Point &q, const vector<Point> &p) {
	int cnt = 0;
	for (int i = 0; i < (int)p.size(); ++i) {
		Point a = p[i], b = p[(i + 1) % p.size()];
		if (onLine(Segment(a, b), q) && onSeg(Segment(a, b), q)) {
			return false;
		}
		if (sign(a.y - b.y) <= 0) {
			swap(a, b);
		}
		if (sign(q.y - a.y) > 0) {
			continue;
		}
		if (sign(q.y - b.y) <= 0) {
			continue;
		}
		cnt += sign(det(b - q, a - q)) > 0;
	}
	return cnt & 1;
}

int n;

vector<vector<Point> > polys;

bool legal(const Segment &s) {
	if (sign((s.b - s.a).len()) == 0) {
		return true;
	}
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < (int)polys[i].size(); ++j) {
			Segment l(polys[i][j], polys[i][(j + 1) % polys[i].size()]);
			if (parallel(s, l)) {
				continue;
			}
			Point p = intersect(s, l);
			if (inSeg(s, p) && onSeg(l, p)) {
				return false;
			}
		}
		if (inside(s.mid(), polys[i])) {
			return false;
		}
	}
	return true;
}

const double FAR = 1e6;

Point getSafe(const Point &p, const Point &b) {
	Point d = p - b;
	d = d / d.len();
	Segment s(p, p + d * FAR);
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < (int)polys[i].size(); ++j) {
			Segment l(polys[i][j], polys[i][(j + 1) % polys[i].size()]);
			if (parallel(s, l)) {
				continue;
			}
			Point p = intersect(s, l);
			if (inSeg(s, p) && onSeg(l, p)) {
				s.b = p;
			}
		}
		if (inside(s.mid(), polys[i])) {
			return p;
		}
	}
	return s.b;
}

const double INF = 1e9;

const int M = 505;

double g[M][M];

Point a, b;

int main() {
	while (scanf("%d", &n) == 1 && n) {
		a = Point(0, 0);
		b.in();
		vector<Point> ps;
		polys.clear();
		for (int i = 0; i < n; ++i) {
			int m;
			scanf("%d", &m);
			vector<Point> poly(m);
			for (int j = 0; j < m; ++j) {
				poly[j].in();
				ps.push_back(poly[j]);
			}
			polys.push_back(poly);
		}
		double ans = INF;
		if (!legal(Segment(a, b))) {
			ans = 0;
		} else {
			for (int i = 0; i <= ps.size(); ++i) {
				Point a = i ? ps[i - 1] : ::a;
				g[i][i] = 0;
				for (int j = i + 1; j <= ps.size(); ++j) {
					Point b = ps[j - 1];
					if (legal(Segment(a, b))) {
						g[i][j] = g[j][i] = (b - a).len();
					} else {
						g[i][j] = g[j][i] = INF;
					}
				}
			}
			for (int k = 0; k <= ps.size(); ++k) {
				for (int i = 0; i <= ps.size(); ++i) {
					for (int j = 0; j <= ps.size(); ++j) {
						g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
					}
				}
			}
			for (int i = 0; i < ps.size(); ++i) {
				Point block = ps[i];
				if (!legal(Segment(b, block))) {
					continue;
				}
				Segment safe(block, getSafe(block, b));
				if (sign((safe.b - safe.a).len()) == 0) {
					continue;
				}
				for (int j = 0; j <= (int)ps.size(); ++j) {	
					Point term = j ? ps[j - 1] : a,
						  target = project(safe, term);
					if (onSeg(safe, target) && legal(Segment(target, term))) {
						ans = min(ans, g[0][j] + (term - target).len());
					}
				}
			}
		}
		printf("%.12f\n", ans);
	}
	return 0;
}

Measured memory_bytes: 3264