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

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define inf (1<<29)
#define EPS (1e-10)
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define MAX 2000
#define pow2(a) ((a)*(a))
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0


using namespace std;

//


class Point
{
  public:
  double x,y;

  Point(double x = -inf,double y = -inf): x(x),y(y){}

  Point operator + (Point p){return Point(x+p.x,y+p.y);}
  Point operator - (Point p){return Point(x-p.x,y-p.y);}
  Point operator * (double a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}

  bool operator < (const Point& p) const
  {
    return !equals(x,p.x)?x<p.x:y<p.y;
  }

  bool operator == (const Point& p)const
  {
    return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
  }

};

struct Segment
{
  Point p1,p2;
  Segment(Point p1 = Point(-inf,-inf),Point p2 = Point(-inf,-inf)):p1(p1),p2(p2){}
  bool operator == (const Segment& p)const
  {
    return p.p1 == p1 && p.p2 == p2;
  }
};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

ostream& operator << (ostream& os,const Point& a)
{
  os << "(" << a.x << "," << a.y << ")";
}

ostream& operator << (ostream& os,const Segment& a)
{
  os << "( " << a.p1 << " , " << a.p2 << " )";
}

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

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

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

//rad は角度をラジアンで持たせること
Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

// 度をラジアンに変換
double toRad(double agl){ return agl*M_PI/180.0; }

int ccw(Point p0,Point p1,Point p2)
{
  Point a = p1-p0;
  Point b = p2-p0;
  if(cross(a,b) > EPS)return COUNTER_CLOCKWISE;
  if(cross(a,b) < -EPS)return CLOCKWISE;
  if(dot(a,b) < -EPS)return ONLINE_BACK;
  if(norm(a) < norm(b))return ONLINE_FRONT;
  return ON_SEGMENT;
}

bool intersectLL(Line l, Line m) {
  return abs(cross(l.p2-l.p1, m.p2-m.p1)) > EPS || // non-parallel
         abs(cross(l.p2-l.p1, m.p1-l.p1)) < EPS;   // same line
}
bool intersectLS(Line l, Line s) {
  return cross(l.p2-l.p1, s.p1-l.p1)*       // s[0] is left of l
         cross(l.p2-l.p1, s.p2-l.p1) < EPS; // s[1] is right of l
}
bool intersectLP(Line l,Point p) {
  return abs(cross(l.p2-p, l.p1-p)) < EPS;
}
bool intersectSS(Line s, Line t) {
  return ccw(s.p1,s.p2,t.p1)*ccw(s.p1,s.p2,t.p2) <= 0 &&
         ccw(t.p1,t.p2,s.p1)*ccw(t.p1,t.p2,s.p2) <= 0;
}
bool intersectSP(Line s, Point p) {
  return abs(s.p1-p)+abs(s.p2-p)-abs(s.p2-s.p1) < EPS; // triangle inequality
}

Point projection(Line l,Point p) {
  double t = dot(p-l.p1, l.p1-l.p2) / norm(l.p1-l.p2);
  return l.p1 + (l.p1-l.p2)*t;
}
Point reflection(Line l,Point p) {
  return p + (projection(l, p) - p) * 2;
}
double distanceLP(Line l, Point p) {
  return abs(p - projection(l, p));
}
double distanceLL(Line l, Line m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m.p1);
}

double distanceLS(Line l, Line s) {
  if (intersectLS(l, s)) return 0;
  return min(distanceLP(l, s.p1), distanceLP(l, s.p2));
}
double distanceSP(Line s, Point p) {
  Point r = projection(s, p);
  if (intersectSP(s, r)) return abs(r - p);
  return min(abs(s.p1 - p), abs(s.p2 - p));
}

double distanceSS(Line s, Line t) {
  if (intersectSS(s, t)) return 0;
  return min(min(distanceSP(s, t.p1), distanceSP(s, t.p2)),
             min(distanceSP(t, s.p1), distanceSP(t, s.p2)));
}
Point crosspoint(Line l, Line m) {
  double A = cross(l.p2 - l.p1, m.p2 - m.p1);
  double B = cross(l.p2 - l.p1, l.p2 - m.p1);
  if (abs(A) < EPS && abs(B) < EPS) return m.p1; // same line
  if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!!
  return m.p1 +   (m.p2 - m.p1) * (B / A);
}

//

struct Poxas7
{
  int cur;
  double cost;
  Poxas7(int cur=inf,double cost=inf):cur(cur),cost(cost){}
  bool operator < (const Poxas7 &a)const
  {
    return cost > a.cost;
  }
};

int path[MAX],AN,BN,N;
double mincost[MAX];
vector<Point> vec[2];

double dijkstra(vector<Point> &vec,int s,int t,vector<Segment> &ban)
{
  N = vec.size();
  rep(i,N)path[i] = -1,mincost[i] = inf;
  priority_queue<Poxas7> Q;
  Q.push(Poxas7(s,0));
  mincost[s] = 0;
  while(!Q.empty())
    {
      Poxas7 pox = Q.top(); Q.pop();

      if(pox.cur == t)
	{
	  return pox.cost;
	}

      rep(next,N)
	{
	  if(s == next)continue;
	  Segment seg = Segment(vec[pox.cur],vec[next]);	  
	  bool out = false;
	  rep(i,ban.size())
	    if(intersectSS(ban[i],seg))
	      {
		out = true;
		break;
	      }
	  if(out)continue;

	  if(mincost[next] > pox.cost + abs(vec[pox.cur]-vec[next]))
	    {
	      path[next] = pox.cur;
	      mincost[next] = pox.cost + abs(vec[pox.cur]-vec[next]);
	      Q.push(Poxas7(next,mincost[next]));
	    }
	}

    }
  return -1;
}

int main()
{
  while(scanf("%d %d",&AN,&BN) != EOF)
    {
      rep(i,2)vec[i].clear();
      vec[0].resize(AN);
      vec[1].resize(BN);
      rep(i,AN)cin >> vec[0][i].x >> vec[0][i].y;
      rep(i,BN)cin >> vec[1][i].x >> vec[1][i].y;      

      double ans = inf;
      rep(i,2)
	{
	  vector<Segment> ban;
	  double cost = dijkstra(vec[i],0,1,ban);
	  if(cost == -1)continue;
	  int cur = 1;

	  for(int next=path[cur];cur != 0;cur=next,next=path[cur])
	    {
	      ban.push_back(Segment(vec[i][cur],vec[i][next]));
	    }

	  double cost2 = dijkstra(vec[(i+1)%2],0,1,ban);
	  if(cost2 == -1)continue;
	  ans = min(ans,cost+cost2);
	}

      if(ans == inf)cout << "-1" << endl;      
      else          cout << setiosflags(ios::fixed) << setprecision(15) << ans << endl;
    }
  return 0;
}

Measured memory_bytes: 1484