#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


enum Type{
	A,
	B,
};

struct Data{
	Data(int arg_node_id,double arg_sum_dist){
		node_id = arg_node_id;
		sum_dist = arg_sum_dist;
	}
	bool operator<(const struct Data &arg) const{
		return sum_dist > arg.sum_dist;
	}
	int node_id;
	double sum_dist;
};


struct Point{
	double x,y;
};

struct Line{
	Point p[2];
};

double calc_dist(Line a){
	return sqrt((a.p[0].x-a.p[1].x)*(a.p[0].x-a.p[1].x)+(a.p[0].y-a.p[1].y)*(a.p[0].y-a.p[1].y));
}


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.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}


Point point[2][1000];
double min_dist[1000],DIST[2][1000][1000];
int start = 0,goal = 1;
Line base_line;


double dijkstra(int data_num,Type type){

	min_dist[start] = 0;
	for(int i = 1; i < data_num; i++)min_dist[i] = DBL_MAX;

	priority_queue<Data> Q;
	Q.push(Data(start,0));

	double tmp_dist;

	Line line;

	while(!Q.empty()){

		if(Q.top().node_id == goal){
			Q.pop();
		}else if(Q.top().sum_dist > min_dist[Q.top().node_id]){
			Q.pop();
		}else{

			line.p[0] = point[type][Q.top().node_id];

			for(int next_node = 0; next_node < data_num; next_node++){
				if(next_node == Q.top().node_id)continue;

				line.p[1] = point[type][next_node];

				if(is_Cross(line,base_line))continue;

				tmp_dist = DIST[type][Q.top().node_id][next_node];

				if(min_dist[next_node] > Q.top().sum_dist+tmp_dist){
					min_dist[next_node] = Q.top().sum_dist+tmp_dist;
					Q.push(Data(next_node,min_dist[next_node]));
				}
			}
			Q.pop();
		}
	}

	return min_dist[goal];
}

int main(){

	int N_A,N_B;
	scanf("%d %d",&N_A,&N_B);

	for(int i = 0; i < N_A; i++){
		scanf("%lf %lf",&point[A][i].x,&point[A][i].y);
	}

	Line calc_line;
	double tmp_dist;

	for(int i = 0; i < N_A-1; i++){
		calc_line.p[0] = point[A][i];
		for(int k = i+1; k < N_A; k++){
			calc_line.p[1] = point[A][k];
			tmp_dist = calc_dist(calc_line);
			DIST[A][i][k] = tmp_dist;
			DIST[A][k][i] = tmp_dist;
		}
	}

	for(int i = 0; i < N_B; i++){
		scanf("%lf %lf",&point[B][i].x,&point[B][i].y);
	}

	for(int i = 0; i < N_B-1; i++){
		calc_line.p[0] = point[B][i];
		for(int k = i+1; k < N_B; k++){
			calc_line.p[1] = point[B][k];
			tmp_dist = calc_dist(calc_line);
			DIST[B][i][k] = tmp_dist;
			DIST[B][k][i] = tmp_dist;
		}
	}

	double dist_1,dist_2;

	base_line.p[0] = point[A][0];
	base_line.p[1] = point[A][1];

	dist_1 = dijkstra(N_B,B);

	if(fabs(dist_1-DBL_MAX)<EPS){
		//Do nothing
	}else{
		dist_1 += calc_dist(base_line);
	}

	base_line.p[0] = point[B][0];
	base_line.p[1] = point[B][1];

	dist_2 = dijkstra(N_A,A);

	if(fabs(dist_2-DBL_MAX)<EPS){
		//Do nothing
	}else{
		dist_2 += calc_dist(base_line);
	}

	double ans = min(dist_1,dist_2);

	if(fabs(ans-DBL_MAX) < EPS){
		printf("-1\n");
	}else{
		printf("%.12lf\n",ans);
	}

	return 0;
}

Measured memory_bytes: 18972