Problem:
Problem I: Wind Passages

Wind Corridor is a covered passageway where strong wind is always blowing. It is a long corridor of
width W, and there are several pillars in it. Each pillar is a right prism and its face is a polygon (not
necessarily convex).

In this problem, we consider two-dimensional space where the positive x-axis points the east and the
positive y-axis points the north. The passageway spans from the south to the north, and its length is
infinity. Specifically, it covers the area 0 ≤ x ≤ W. The outside of the passageway is filled with walls.
Each pillar is expressed as a polygon, and all the pillars are located within the corridor without conflicting
or touching each other.

Wind blows from the south side of the corridor to the north. For each second, w unit volume of air can
be flowed at most if the minimum width of the path of the wind is w. Note that the path may fork and
merge, but never overlaps with pillars and walls.

Your task in this problem is to write a program that calculates the maximum amount of air that can be
flowed through the corridor per second.

Input

The input consists of multiple datasets. Each dataset has the following format:

The first line of the input contains two integers W and N. W is the width of the corridor, and N is the
number of pillars. W and N satisfy the following condition: 1 ≤ W ≤ 104 and 0 ≤ N ≤ 200.

Then, N specifications of each pillar follow. Each specification starts with a line that contains a single
integer M, which is the number of the vertices of a polygon (3 ≤ M ≤ 40). The following M lines describe the shape of the polygon. The i-th line (1 ≤ i ≤ M) contains two integers xi and yi that denote the coordinate of the i-th vertex (0 < xi < W, 0 < yi < 104).

The last dataset is followed by a line containing two zeros. This line is not a part of any dataset and should not be processed.

Output

For each dataset, your program should print a line that contains the maximum amount of air flow per second, in unit
volume. The output may contain arbitrary number of digits after the decimal point, but the absolute error
must not exceed 10-6.

Sample Input

5 2
4
1 1
1 2
2 2
2 1
4
3 3
3 4
4 4
4 3
0 0

Output for the Sample Input

3.41421356

Solution in C++ (judge verdict: Accepted)

#include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 205

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	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); }

	double abs(){ 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 fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}

	double x,y;
};
typedef Point Vector;
typedef vector<Point> Polygon;

struct Segment{
	void set(double x1,double y1,double x2,double y2){
		p1.x = x1;
		p1.y = y1;
		p2.x = x2;
		p2.y = y2;
	}
	Point p1,p2;
};

struct Line{
	Line(Point a,Point b){
		p1 = a;
		p2 = b;
	}
	Point p1,p2;
};

int N,start,goal;
int num_point[NUM];
double W;
double min_dist[NUM][NUM];
Polygon polygon[NUM];


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

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

Point calc_minus(Point a,Point b){
	Point ret;

	ret.x = a.x-b.x;
	ret.y = a.y-b.y;

	return ret;
}

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

double getDistanceLP(Segment l,Point p){
	return fabs(cross(calc_minus(l.p2,l.p1),calc_minus(p,l.p1))/calc_len(calc_minus(l.p2,l.p1)));
}

double getDistanceSP(Segment s,Point p){
	if(dot(calc_minus(s.p2,s.p1),calc_minus(p,s.p1)) < 0.0)return calc_len(calc_minus(p,s.p1));
	if(dot(calc_minus(s.p1,s.p2),calc_minus(p,s.p2)) < 0.0)return calc_len(calc_minus(p,s.p2));
	return getDistanceLP(s,p);
}

double getDistance(Segment s1,Segment s2){
	return min(min(getDistanceSP(s1,s2.p1),getDistanceSP(s1,s2.p2)),
			min(getDistanceSP(s2,s1.p1),getDistanceSP(s2,s1.p2)));
}

double getDistance(int p1,int p2){

	double ret = BIG_NUM;
	Segment s1,s2;

	for(int i = 0; i < num_point[p1]; i++){

		s1.set(polygon[p1][i].x,polygon[p1][i].y,polygon[p1][(i+1)%num_point[p1]].x,polygon[p1][(i+1)%num_point[p1]].y);
		for(int k = 0; k < num_point[p2]; k++){
			s2.set(polygon[p2][k].x,polygon[p2][k].y,polygon[p2][(k+1)%num_point[p2]].x,polygon[p2][(k+1)%num_point[p2]].y);

			ret = min(ret,getDistance(s1,s2));
		}
	}

	return ret;
}

int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}

bool is_Cross(Line a,Line b){

	if(func(a.p1.x,a.p1.y,a.p2.x,a.p2.y,b.p1.x,b.p1.y)*
			func(a.p1.x,a.p1.y,a.p2.x,a.p2.y,b.p2.x,b.p2.y) <= 0 &&
			func(b.p1.x,b.p1.y,b.p2.x,b.p2.y,a.p1.x,a.p1.y)*
			func(b.p1.x,b.p1.y,b.p2.x,b.p2.y,a.p2.x,a.p2.y) <= 0){
		return true;
	}
	return false;
}
/*
 * IN 2
 * ON 1
 * OUT 0
 *
 */
int contains(Polygon g,Point p){
	int n = g.size();
	bool x = false;
	for(int i = 0; i < n; i++){
		Point a = g[i]-p,b = g[(i+1)%n]-p;
		if(abs(cross(a,b)) < EPS && dot(a,b) < EPS)return 1;
		if(a.y > b.y)swap(a,b);
		if(a.y < EPS && EPS < b.y && cross(a,b) > EPS) x = !x;
	}
	return (x ? 2:0);
}

//他角形g1とg2が交差するかどうか調べる関数
bool intersect(const Polygon g1,const Polygon g2){

	int size_1 = g1.size(),size_2 = g2.size();

	for(int i = 0; i < size_1; i++){
		for(int k = 0; k < size_2; k++){
			if(is_Cross(Line(g1[i],g1[(i+1)%size_1]),Line(g2[k],g2[(k+1)%size_2]))){
				return true;
			}
		}
	}

	for(int i = 0; i < size_1; i++){
		if(contains(g2,g1[i]))return true;
	}

	for(int i = 0; i < size_2; i++){
		if(contains(g1,g2[i]))return true;
	}

	return false;
}

void calc(){


	for(int i = 0; i < N; i++){
		polygon[i].clear();
	}

	Point tmp_point;

	for(int i = 0; i < N; i++){

		scanf("%d",&num_point[i]);

		for(int k = 0; k < num_point[i]; k++){
			scanf("%lf %lf",&tmp_point.x,&tmp_point.y);
			polygon[i].push_back(tmp_point);
		}
	}

	start = N;
	goal = N+1;

	for(int i = 0; i <= N+1; i++){
		for(int k = 0; k <= N+1; k++){
			if(k == i){
				min_dist[i][k] = 0;
			}else{
				min_dist[i][k] = (double)BIG_NUM;
			}
		}
	}

	min_dist[start][goal] = W;

	for(int k = 0; k < N; k++){

		for(int i = 0; i < polygon[k].size(); i++){
			min_dist[start][k] = min(min_dist[start][k],polygon[k][i].x);
		}
		for(int adj = 0; adj < N; adj++){
			if(intersect(polygon[k],polygon[adj])){

				min_dist[k][adj] = 0;

			}else{

				min_dist[k][adj] = getDistance(k,adj);
			}
		}
		for(int i = 0; i < polygon[k].size(); i++){
			min_dist[k][goal] = min(min_dist[k][goal],W-polygon[k][i].x);
		}
	}

	for(int mid = 0; mid <= N+1; mid++){
		for(int start = 0; start <= N+1; start++){
			if(fabs(min_dist[start][mid]-BIG_NUM) < EPS)continue;
			for(int goal = 0; goal <= N+1; goal++){
				if(fabs(min_dist[mid][goal]-BIG_NUM) < EPS)continue;
				min_dist[start][goal] = min(min_dist[start][goal],min_dist[start][mid]+min_dist[mid][goal]);
			}
		}
	}

	printf("%.10lf\n",min_dist[start][goal]);
}


int main(){

	while(true){
		scanf("%lf %d",&W,&N);
		if(W == 0 && N == 0)break;

		calc();
	}

	return 0;
}