#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <map>
#include <numeric>
#include <queue>
#include <deque>
#include <list>
#include <stack>
#include <deque>
#include <cmath>
#include <complex>
#include <cassert>
#include <cstring>
#include <functional>
#include <bitset>
#include <climits>
#include <random>
#include <unordered_set>
#include <unordered_map>
#include <chrono>

using namespace std;
#define EPS 1e-10
#define rep(i,n) for(int i=0;i<n;i++)
typedef complex<double> C;

const double PI = 4*atan(1.0);

bool eq(double a,double b)
{
  return (-EPS<a-b&&a-b<EPS);
}

namespace std
{
    bool operator < (const C a, const C b) {
        return a.real() != b.real() ? a.real() < b.real() : a.imag() < b.imag();
    }
    bool operator > (const C a, const C b) {
        return a.real() != b.real() ? a.real() > b.real() : a.imag() > b.imag();
    }
    bool operator==(const C a, const C b){
        return (eq(a.real(),b.real()) && eq(a.imag(),b.imag()));
    }
    bool operator!=(const C a, const C b){
        return !(a == b);
    }
    C operator* (const C a, const C b){
        return C(a.real()*b.real()-a.imag()*b.imag(),a.real()*b.imag()+a.imag()*b.real());
    }
}

struct L : public vector<C>
{
    L(){}
    L(const C a, const C b) {
        push_back(a); push_back(b);
    }
};


//条件付きsqrt
double Sqrt(double x)
{
    if(x<0) return 0;
    else    return sqrt(x);
}

//正規化
C normalize(C c)
{
    return c / abs(c);
}

//角度(rad)
double getarg(C a,C b){
    return arg(b*conj(a));
}

//外積
double cross(const C a, const C b)
{
    return imag(conj(a)*b);
}
//内積
double dot(const C a, const C b)
{
    return real(conj(a)*b);
}

//bを中心としてaをth(rad)回転
C rot(C a,C b,double th)
{
    return b + (a-b) * C(cos(th),sin(th));
}

int ccw(C a, C b, C c)
{
    b -= a; c -= a;
    if(cross(b, c) > 0)   return +1;       // counter clockwise
    if(cross(b, c) < 0)   return -1;       // clockwise
    if(dot(b, c) < 0)     return +2;       // c--a--b on line
    if(norm(b) < norm(c)) return -2;       // a--b--c on line
    return 0;   // a--c--b on line
}

//直線どうしの交差判定(同一直線はTrue)
bool intersectLL(const L& l, const L& m)
{
    return abs(cross(l[1]-l[0], m[1]-m[0])) > EPS || abs(cross(l[1]-l[0], m[0]-l[0])) < EPS;
}
//直線と線分の交差判定(一点共有も交差と判定)
bool intersectLS(const L& l, const L& s)
{
    return cross(l[1]-l[0], s[0]-l[0]) * cross(l[1]-l[0], s[1]-l[0]) < EPS;
}
//直線と点の交差(共有)判定
bool intersectLP(const L& l, const C p)
{
    return abs(cross(l[1]-p, l[0]-p)) < EPS;
}
//線分どうしの交差判定(一点共有も交差と判定)
bool intersectSS(const L& s, const L& t)
{
    return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 && ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}
//線分と点の交差(共有)判定
bool intersectSP(const L& s, const C p)
{
    return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS;
}
template<typename T> class Dijkstra {
public:
	struct edge{
		int to; T cost;
	};
	int V;
	vector<vector<edge> > G;
	vector<T> d;
	using pti = pair<T,int>;
	Dijkstra(int node_size) : V(node_size), G(V), d(V, numeric_limits<T>::max()){}
	//無向グラフの場合
	void add_edge(int u,int v,T cost){
		G[u].push_back((edge){v,cost}),G[v].push_back((edge){u,cost});
	}
	void solve(int s){
		priority_queue<pti,vector<pti>,greater<pti> > que;
		d[s] = 0;
		que.push(pti(0,s));
		while(!que.empty()){
			pti p = que.top();
			que.pop();
			int v = p.second;
			if(d[v] < p.first) continue;
			for(auto& w : G[v]){
				if(d[w.to] > d[v] + w.cost){
					d[w.to] = d[v] + w.cost;
					que.push(pti(d[w.to],w.to));
				}
			}
		}
	}
};

double solve(vector<C> a,vector<C>b){
    int n,m;
    n = a.size();
    m = b.size();
    double res = 0;
    res += sqrt(dot(a[0]-a[1],a[0]-a[1]));
    L s(a[0],a[1]);
    Dijkstra<double> dj(m);
    rep(i,m){
        rep(j,m){
            if(i<=j)break;
            L t(b[i],b[j]);
            if(intersectSS(s,t)){
                //cerr << i << " " << j << endl;
            }else{
                dj.add_edge(i,j,sqrt(dot(b[i]-b[j],b[i]-b[j])));
            }
        }
    }
    dj.solve(0);
    return res+dj.d[1];
}


int main(){
    int n,m;
    cin >> n >> m;
    vector<C> a(n);
    vector<C> b(m);
    rep(i,n){
        double s,t;
        cin >> s >> t;
        a[i] = C(s,t);
    }
    rep(i,m){
        double s,t;
        cin >> s >> t;
        b[i] = C(s,t);
    }
    double res = solve(a,b);
    res = min(res,solve(b,a));
    cout.precision(20);
    
    if(res<=1000000000.0)cout << res << endl;
    else cout << -1 << endl;
    return 0;
}


Measured memory_bytes: 19480