Problem:
Problem E: 街を駆ける道

ネーヴァ王国には、トタタ族とツテテ族、２種類の民族が暮らしている。トタタ族の最大の特徴は、
酢豚にパイナップルを入れて食べることである。だがツテテ族は、パイナップルに酢豚を入れて食べ
る。こんな２つの民族がお互いに仲良くやっていけるはずもなく、トタタ族とツテテ族は、何百年も
の昔からずっといがみ合いを続けてきた。

そんなある日、ネーヴァ王のもとに、２つの民族から嘆願書が届いた。それによるとトタタ族は、自
分たちが暮らす街Ａと街Ｂのあいだを結ぶ道を建設してほしいらしい。一方でツテテ族も、自分たち
が暮らす街Ｃと街Ｄのあいだを結ぶ道を建設してほしいらしい。

２つの民族が衝突するのを防ぐため、トタタ族が通る道とツテテ族が通る道を交差させることはでき
ない。また、技術的な制約により、２つの街のあいだを一直線に結ぶような道しか建設することはで
きない。つまり、必要ならば街Ａと街Ｂを直接道で結ばずに、いくつかのトタタ族の街を経由して街
Ａと街Ｂを間接的に結ぶことになるだろう（もちろん、ツテテ族の街を経由してはならない）。その
際、トタタ族の街を結ぶ道どうしは交差していてもよい。街Ｃと街Ｄについても同様である。

道を建設するには、その長さに比例したコストがかかる。なので、条件をみたしつつ、できるだけ建
設する道の長さの合計が短くなるようにしたい。さて、長さの最小値はいくつになるだろうか。

Input

NA NB

xA,1 yA,1

xA,2 yA,2

.

.

.

xA,NA yA,NA

xB,1 yB,1

xB,2 yB,2

.

.

.

xB,NB yB,NB

入力の１行目には、整数NA（2 ≤ NA ≤ 1,000）と整数NB（2 ≤ NB ≤ 1,000）が、空白区切りで書かれている。これは、ネーヴァ王国にはトタタ族が暮らす街がNA 個、ツテテ族が暮らす街がNB 個あることをあらわす。初期状態では、どこにも道は建設されていない。

続くNA 行には、整数xA,i（-10,000 ≤ xA,i ≤ 10,000）と整数yA,i（-10,000 ≤ yA,i ≤ 10,000）が、空白区切りで書かれている。ネーヴァ王国の地理は２次元直交座標平面であらわされ、１＋ i 行目に書かれた整数xA,i とyA,i は、トタタ族が暮らすi 番目の街の位置座標が(xA,i, yA,i) であることをあらわす。(xA,1, yA,1) と(xA,2, yA,2) が、結ぶべき２つの街の座標である。

続くNB 行には、整数xB,i（-10,000 ≤ xB,i ≤ 10,000）と整数yB,i（-10,000 ≤ yB,i ≤ 10,000）が、空白区切りで書かれている。１＋ NA ＋ i 行目に書かれた整数xB,i とyB,i は、ツテテ族が暮らすi 番目の街の位置座標が(xB,i, yB,i) であることをあらわす。(xB,1, yB,1) と(xB,2, yB,2) が、結ぶべき２つの街の座標である。

どの２つの街の座標も異なっており、どの３つの街も同一直線上にないと仮定してよい。

Output

問題文の条件をみたすように道を建設したとき、道の長さの合計の最小値を出力せよ。ここで言う
「長さ」とは、ユークリッド距離のことである。ただし、どうやっても条件をみたす道を建設できな
いときは、代わりに-1 を出力せよ。出力は誤差を含んでいてもよいが、真の値との相対誤差が10-9未満でなければならない。

Sample Input 1

2 2
0 0
1 1
2 0
2 -1

Sample Output 1

2.414213562373

Sample Input 2

2 3
4 0
0 0
2 3
2 -2
3 1

Sample Output 2

-1

Sample Input 3

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

Sample Output 3

12.359173603117

Solution in C (judge verdict: Accepted)

// AOJ 2334 Roads on Towns
// 2018.2.24 bal4u

#include <stdio.h>
#include <math.h>

#define EPS			1e-10
#define INF			1e20
typedef struct { double x, y; } PP;

PP p[2][1002];

PP vectorSub(PP p1, PP p2) { PP r; r.x = p1.x - p2.x, r.y = p1.y - p2.y; return r; }
double cross(PP a, PP b) { return a.x * b.y - a.y * b.x; }
double dot(PP a, PP b) { return a.x * b.x + a.y * b.y; }
double norm(PP a) { return a.x * a.x + a.y * a.y; }
double vectorAbs(PP a) { return hypot(a.x, a.y); }

int ccw(PP p0, PP p1, PP p2)
{
	PP a = vectorSub(p1, p0), b = vectorSub(p2, p0);
	double t = cross(a, b);
	if (t >  EPS) return 1;
	if (t < -EPS) return -1;
	if (dot(a, b) < -EPS) return 2;
	if (norm(a) < norm(b)) return -2;
	return 0;
}

int intersect(PP p1, PP p2, PP p3, PP p4)
{
	return ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 &&
		   ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0;
}

//#define getchar_unlocked()  getchar()
int in()
{
	int n = 0;
	int c = getchar_unlocked();
	if (c == '-') {
		c = getchar_unlocked();
		do n = (n<<3)+(n<<1) + (c & 0xf), c = getchar_unlocked();
		while (c >= '0');
		return -n;
	}
	do n = (n<<3)+(n<<1) + (c & 0xf), c = getchar_unlocked();
	while (c >= '0');
	return n;
}

double calc(PP s, PP g, PP *a, int n, PP es, PP eg)
{
	int i, j;
	double ans, x, y, z;

	if (!intersect(s, g, es, eg)) return vectorAbs(vectorSub(s, g));
	if (n == 0) return INF+100;

	ans = INF+100;
	for (i = 0; i < n; i++) {
		if (intersect(s, a[i], es, eg)) continue;
		x = vectorAbs(vectorSub(s, a[i]));
		if (x >= ans) continue;
		if (!intersect(g, a[i], es, eg)) {
			y = vectorAbs(vectorSub(g, a[i]));
			if (x + y < ans) ans = x + y;
			continue;
		}
		for (j = 0; j < n; j++) if (j != i) {
			if (intersect(a[i], a[j], es, eg)) continue;
			y = vectorAbs(vectorSub(a[i], a[j]));
			if (x + y  >= ans) continue;
			if (!intersect(g, a[j], es, eg)) {
				z = vectorAbs(vectorSub(g, a[j]));
				if (x + y + z < ans) ans = x + y + z;
			}
		}
	}
	return ans;
}

int main()
{
	int i, j, n[2];
	PP s[2], g[2];
	double ans, x;

	n[0] = in()-2, n[1] = in()-2;
	for (i = 0; i < 2; i++) {
		s[i].x = in(), s[i].y = in();
		g[i].x = in(), g[i].y = in();
		for (j = 0; j < n[i]; j++) p[i][j].x = in(), p[i][j].y = in();
	}

	ans = INF+100;
	for (i = 0; i < 2; i++) {
		x = vectorAbs(vectorSub(s[1-i], g[1-i])) + calc(s[i], g[i], p[i], n[i], s[1-i], g[1-i]);
		if (x < ans) ans = x;
	}

	if (ans >= INF) puts("-1");
	else printf("%.12lf\n", ans);
	return 0;
}