#include <iostream>
#include <iomanip>
#include <vector>
#include <cmath>
#include <queue>
#include <cassert>

using namespace std;
using ll = long long;
using ld = double;
using C = pair<ll, ll>;
using L = pair<C, C>;

ll cross(const C a, const C b)
{
    return a.first * b.second - a.second * b.first;
}
ll dot(const C a, const C b)
{
    return a.first * b.first + a.second * b.second;
}
ll normSq(const C a)
{
    return a.first * a.first + a.second * a.second;
}
ld norm(const L a)
{
    const ll dx = a.first.first - a.second.first;
    const ll dy = a.first.second - a.second.second;
    return hypot(dx, dy);
}
int ccw(C a, C b, C c)
{
    b = {b.first - a.first, b.second - a.second};
    c = {c.first - a.first, c.second - a.second};
    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 (normSq(b) < normSq(c))
        return -2;  // a--b--c on line
    return 0;       //b--a--c on line
}
bool intersectSS(const L s, const L t)
{
    return ccw(s.first, s.second, t.first) * ccw(s.first, s.second, t.second) <= 0 and ccw(t.first, t.second, s.first) * ccw(t.first, t.second, s.second) <= 0;
}
struct CostGraph {
    using T = ld;
    CostGraph(const int v) : V{v}
    {
        edge.resize(v);
    }
    struct Edge {
        Edge(const int from, const int to, const T cost) : from{from}, to{to}, cost{cost} {}
        const int from;
        const int to;
        const T cost;
        bool operator<(const Edge& e) const
        {
            return cost != e.cost ? cost < e.cost : to < e.to;
        }
    };
    void addEdge(const int from, const int to, const T cost)
    {
        edge[from].push_back(Edge{from, to, cost});
        edge[to].push_back(Edge{to, from, cost});
    }
    vector<vector<Edge>> edge;
    const int V;
};
void Dijkstra(const CostGraph& g, const int s, vector<CostGraph::T>& d)
{
    using T = CostGraph::T;
    assert(s < g.V);
    assert(d.size() == g.V);
    using P = pair<T, int>;
    priority_queue<P, vector<P>, greater<P>> q;
    for (int i = 0; i < g.V; i++) {
        d[i] = 1e8;
    }
    d[s] = 0;
    q.push(make_pair(0, s));
    while (not q.empty()) {
        const P& p = q.top();
        const T cost = p.first;
        const int v = p.second;
        q.pop();
        if (d[v] < cost) {
            continue;
        }
        for (const auto& e : g.edge[v]) {
            if (d[e.to] > d[v] + e.cost) {
                d[e.to] = d[v] + e.cost;
                q.push(make_pair(d[e.to], e.to));
            }
        }
    }
}

int main()
{
    int A, B;
    cin >> A >> B;
    vector<C> a(A);
    for (int i = 0; i < A; i++) {
        ll x, y;
        cin >> x >> y;
        a[i] = {x, y};
    }
    const L al = L{a[0], a[1]};
    vector<C> b(B);
    for (int i = 0; i < B; i++) {
        ll x, y;
        cin >> x >> y;
        b[i] = {x, y};
    }
    ld mini = 1e8;
    const L bl = L{b[0], b[1]};
    CostGraph ga(A);
    for (int i = 0; i < A; i++) {
        for (int j = i + 1; j < A; j++) {
            if (not intersectSS(bl, L{a[i], a[j]})) {
                ga.addEdge(i, j, norm(L{a[i], a[j]}));
            }
        }
    }
    vector<ld> ad(A);
    Dijkstra(ga, 0, ad);
    mini = min(mini, ad[1] + norm(bl));
    CostGraph gb(B);
    for (int i = 0; i < B; i++) {
        for (int j = i + 1; j < B; j++) {
            if (not intersectSS(al, L{b[i], b[j]})) {
                gb.addEdge(i, j, norm(L{b[i], b[j]}));
            }
        }
    }
    vector<ld> bd(B);
    Dijkstra(gb, 0, bd);
    mini = min(mini, bd[1] + norm(al));
    if (mini == 1e8) {
        cout << -1 << endl;
    } else {
        cout << fixed << setprecision(15) << mini << endl;
    }

    return 0;
}



Measured memory_bytes: 36904