Language: C++

#include <cmath>
#include <queue>
#include <cstdio>
#include <cassert>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

const double EPS=1e-8;
const double INF=1e77;

struct point{
	double x,y;
	point():x(0),y(0){}
	point(double x,double y):x(x),y(y){}
	point &operator+=(const point &a){ x+=a.x; y+=a.y; return *this; }
	point &operator-=(const point &a){ x-=a.x; y-=a.y; return *this; }
	point &operator*=(double c){ x*=c; y*=c; return *this; }
	point &operator/=(double c){ x/=c; y/=c; return *this; }
	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/(double c)const{ return point(x/c,y/c); }
	point operator-()const{ return point(-x,-y); }
	bool operator< (const point &a)const{ return x+EPS<a.x || (abs(x-a.x)<EPS && y+EPS<a.y); }
	bool operator==(const point &a)const{ return abs(x-a.x)<EPS && abs(y-a.y)<EPS; }
	bool operator!=(const point &a)const{ return abs(x-a.x)>EPS || abs(y-a.y)>EPS; }
};

point operator*(double c,const point &a){ return point(c*a.x,c*a.y); }

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

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

double abs(const point &a){ return sqrt(a.x*a.x+a.y*a.y); }

double abs2(const point &a){ return a.x*a.x+a.y*a.y; }

struct line{
	point a,b;
	line(){}
	line(const point &a,const point &b):a(a),b(b){}
	bool operator==(const line &L)const{ return abs(cross(b-a,L.b-L.a))<EPS && abs(cross(L.a-a,L.b-a))<EPS; }
};

struct segment{
	point a,b;
	segment(){}
	segment(const point &a,const point &b):a(a),b(b){}
	operator line()const{ return line(a,b); }
};

typedef vector<point> polygon;

point proj(const point &p,const line &L){ return L.a+dot(p-L.a,L.b-L.a)/abs2(L.b-L.a)*(L.b-L.a); }

enum{CCW=1,CW=-1,ON=0};
int ccw(const point &a,const point &b,const point &c){
	double rdir=cross(b-a,c-a);
	if(rdir> EPS) return CCW;
	if(rdir<-EPS) return CW;
	return ON;
}

bool cover(const segment &S,const point &p){
	return abs(cross(S.a-p,S.b-p))<EPS && dot(S.a-p,S.b-p)<EPS;
}

bool intersect(const segment &S1,const segment &S2){
	if(max(S1.a.x,S1.b.x)+EPS<min(S2.a.x,S2.b.x)
	|| max(S1.a.y,S1.b.y)+EPS<min(S2.a.y,S2.b.y)
	|| max(S2.a.x,S2.b.x)+EPS<min(S1.a.x,S1.b.x)
	|| max(S2.a.y,S2.b.y)+EPS<min(S1.a.y,S1.b.y)) return false;
	return ccw(S1.a,S1.b,S2.a)*ccw(S1.a,S1.b,S2.b)<=0
		&& ccw(S2.a,S2.b,S1.a)*ccw(S2.a,S2.b,S1.b)<=0;
}

point get_intersect(const segment &S1,const segment &S2){
	double a1=cross(S1.b-S1.a,S2.b-S2.a);
	double a2=cross(S1.b-S1.a,S1.b-S2.a);
	if(abs(a1)<EPS){
		if(cover(S1,S2.a)) return S2.a;
		if(cover(S1,S2.b)) return S2.b;
		if(cover(S2,S1.a)) return S1.a;
		return S1.b;
	}
	return S2.a+a2/a1*(S2.b-S2.a);
}

bool cover(const polygon &F,const point &p){
	int n=F.size();
	bool res=false;
	rep(i,n){
		point v1=F[i]-p,v2=F[(i+1)%n]-p;
		if(v1.y>v2.y) swap(v1,v2);
		if(v1.y<EPS && EPS<v2.y && cross(v1,v2)>EPS) res=!res;
		if(abs(cross(v1,v2))<EPS && dot(v1,v2)<EPS) return true;
	}
	return res;
}

bool cover(const polygon &F,const segment &S){
	int n=F.size();
	vector<point> P;
	P.push_back(S.a);
	P.push_back(S.b);
	rep(i,n){
		segment T(F[i],F[(i+1)%n]);
		if(intersect(S,T)) P.push_back(get_intersect(S,T));
	}
	sort(P.begin(),P.end());
	P.erase(unique(P.begin(),P.end()),P.end());

	int m=P.size();
	rep(i,m-1){
		point c=(P[i]+P[i+1])/2;
		if(!cover(F,c)) return false;
	}
	return true;
}

// reflection with line L
point ref(const point &p,const line &L){ return p+2.0*(proj(p,L)-p); }

bool is_passable(const point &s,const point &g,const polygon &F1,const polygon &F2,const line &L){
	return cover(F1,segment(s,g)) && cover(F2,segment(ref(s,L),ref(g,L)));
}

void solve(const polygon &F1,const polygon &F2,const point &s1,const point &s2,const point &g1,const point &g2,const line &L){
	int m1=F1.size(),m2=F2.size();
	vector<point> V; // vertices of graph
	V.push_back(s1);
	V.push_back(g1);
	rep(i,m1) V.push_back(F1[i]);
	rep(j,m2) V.push_back(ref(F2[j],L));
	rep(i,m1) rep(j,m2) {
		segment S1(F1[i],F1[(i+1)%m1]);
		segment S2(ref(F2[j],L),ref(F2[(j+1)%m2],L));
		if(intersect(S1,S2)) V.push_back(get_intersect(S1,S2));
	}

	// Dijkstra
	int n=V.size();
	vector<double> d(n,INF);
	d[0]=0;
	priority_queue< pair<double,int> > Q;
	Q.push(make_pair(0,0));
	while(!Q.empty()){
		double d_now=-Q.top().first;
		int u=Q.top().second; Q.pop();

		if(d_now>d[u]+EPS) continue;
		if(u==1){ printf("%.9f\n",d_now); return; }

		rep(v,n){
			point p=V[u],q=V[v];
			double cost=abs(q-p);
			if(d[v]>d[u]+cost+EPS && is_passable(p,q,F1,F2,L)){
				d[v]=d[u]+cost;
				Q.push(make_pair(-d[v],v));
			}
		}
	}

	puts("impossible");
	return;
}

int main(){
	for(int n;scanf("%d",&n),n;){
		polygon F[100];
		rep(i,n){
			int m; scanf("%d",&m);
			F[i].resize(m);
			rep(j,m) scanf("%lf%lf",&F[i][j].x,&F[i][j].y);
		}
		point s1,g1; scanf("%lf%lf%lf%lf",&s1.x,&s1.y,&g1.x,&g1.y);
		line L; scanf("%lf%lf%lf%lf",&L.a.x,&L.a.y,&L.b.x,&L.b.y);

		point s2=ref(s1,L);
		point g2=ref(g1,L);

		int is1=-1,ig1=-1,is2=-1,ig2=-1;
		rep(i,n){
			if(cover(F[i],s1)) is1=i;
			if(cover(F[i],g1)) ig1=i;
			if(cover(F[i],s2)) is2=i;
			if(cover(F[i],g2)) ig2=i;
		}
		assert(is1!=-1);
		assert(ig1!=-1);
		assert(is1==ig1);

		if(is2==-1 || ig2==-1 || is2!=ig2){ puts("impossible"); continue; }

		solve(F[is1],F[is2],s1,s2,g1,g2,L);
	}

	return 0;
}

Compiler output:
a.cc: In function 'bool cover(const polygon&, const segment&)':
a.cc:112:9: error: 'sort' was not declared in this scope; did you mean 'sqrt'?
  112 |         sort(P.begin(),P.end());
      |         ^~~~
      |         sqrt
a.cc:113:17: error: 'unique' was not declared in this scope
  113 |         P.erase(unique(P.begin(),P.end()),P.end());
      |                 ^~~~~~