#include<bits/stdc++.h>
using namespace std;

/*                         */
/*                         */
/* @@ Geometory Library @@ */
/*               by ei1333 */
/*                         */
const double EPS = 1e-8, PI = acos(-1);
 
inline bool eq(double a,double b){ return abs(b - a) < EPS; }
#define curr(P,i) P[i]
#define next(P,i) P[(i+1)%P.size()]
#define prev(P,i) P[(i+P.size()-1) % P.size()]
enum { OUT, ON, IN };
struct Geometory { // Geometory Library
  struct Point {
    double x, y;
    Point(){};
    Point(double x,double y):x(x),y(y){};
    Point operator+(const Point& b) const { return Point(x + b.x,y + b.y); }
    Point operator-(const Point& b) const { return Point(x - b.x,y - b.y); }
    Point operator*(const double b) const { return Point(x * b,y * b); }
    Point operator*(const Point& b) const { return Point(x * b.x - y * b.y,x * b.y + y * b.x); }
    Point operator/(const double b) const { return Point(x / b,y / b); }
    bool operator< (const Point& b) const { return x != b.x ? x < b.x : y < b.y;}
    bool operator==(const Point& b) const { return eq(x,b.x) && eq(y,b.y); }
    double norm(){ return x * x + y * y; }
    double arg(){ return atan2(x,y); }
    double abs(){ return sqrt(norm()); }
    Point rotate(double theta){ return Point(cos(theta) * x - sin(theta) * y,sin(theta) * x + cos(theta) * y); }
    Point rotate90(){ return Point(-y,x); }
    friend ostream& operator<<(ostream& os, Point& p){ return os<<"("<<p.x<<","<<p.y<<")"; }
    friend istream& operator>>(istream& is, Point& a){ return is>>a.x>>a.y; }
  };
    
  struct Line {
    Point a, b;
    Line(){};
    Line(Point a,Point b):a(a),b(b){};
    friend ostream& operator<<(ostream& os, Line& p){ return os<<"("<<p.a.x<<","<<p.a.y<<") to ("<<p.b.x<<","<<p.b.y<<")"; }
    friend istream& operator>>(istream& is, Line& a){ return is>>a.a.x>>a.a.y>>a.b.x>>a.b.y; }
  };
  struct Segment {
    Point a, b;
    Segment(){};
    Segment(Point a,Point b):a(a),b(b){};
    friend ostream& operator<<(ostream& os, Segment& p){ return os<<"("<<p.a.x<<","<<p.a.y<<") to ("<<p.b.x<<","<<p.b.y<<")"; }
    friend istream& operator>>(istream& is, Segment& a){ return is>>a.a.x>>a.a.y>>a.b.x>>a.b.y; }
    double abs(){ return (a - b).abs(); }
  };
  struct Circle {
    Point p; double r;
    Circle(){};
    Circle(Point p, double r) : p(p),r(r){};
  };
  typedef vector< Point > Polygon;
  typedef vector< Segment > Segments;
  typedef vector< Line > Lines;
  typedef vector< Circle > Circles;
  typedef pair< Point, Point > PointPoint;
    
  double cross(const Point& a,const Point& b){
    return a.x * b.y - a.y * b.x;
  }
  double dot(const Point& a,const Point& b){
    return a.x * b.x + a.y * b.y;
  }
    
  int ccw(const Point& a,Point b,Point c){
    b = b - a, c = c - a;
    if(cross(b,c) > EPS)    return +1;  // a → b で 反時計方向におれて c
    if(cross(b,c) < -EPS)    return -1; // a → b で 時計方向におれて c
    if(dot(b,c) < 0)      return +2;  // c -- a -- bで一直線上
    if(b.norm() < c.norm()) return -2; // a -- b -- cで一直線上
    return 0;  // a -- c -- bで一直線上
  }
  Point Projection(const Line& l, const Point& p){
    double t = dot( p - l.a, l.a - l.b) / (l.a - l.b).norm();
    return l.a + (l.a - l.b) * t;
  }
  Point Projection(const Segment& l, const Point& p){
    double t = dot( p - l.a, l.a - l.b) / (l.a - l.b).norm();
    return l.a + (l.a - l.b) * t;
  }
  Point Reflection(const Line& l, const Point& p){
    return p + (Projection( l, p) - p) * 2.0;
  }
    
  double Distance( const Line& l,const Point& p) { //OK
    return (p - Projection( l, p)).abs();
  }
    
  bool Intersect(const Line& l, const Line& m){
    return abs(cross(l.b - l.a, m.b - m.a)) > EPS || abs(cross(l.b-l.a, m.b-l.a)) < EPS;
  }
  bool Intersect(const Line& l, const Segment& s){
    return cross( l.b - l.a, s.a - l.a) * cross( l.b - l.a, s.b - l.a) < EPS;
  }
  bool Intersect(const Line& l, const Point& p){
    return abs(ccw(l.a, l.b, p)) != -1;
  }
  bool Intersect(const Segment& s, const Segment& t){
    return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
  }
  bool Intersect(const Segment& s, const Point& p){
    return ccw(s.a, s.b, p) == 0;
  }
  bool Intersect(const Circle& c,const Line& l){
    return Distance( l, c.p) <= c.r + EPS;
  }
  bool Intersect(const Circle& c,const Point& p){
    return abs( ( p - c.p).abs() - c.r ) < EPS;
  }
  int Intersect(const Circle& c, const Segment& l){
    if( (Projection( l, c.p) - c.p).norm() - c.r * c.r > EPS) return 0;
    const double d1 = ( c.p - l.a).abs(), d2 = ( c.p - l.b).abs();
    if( d1 < c.r + EPS && d2 < c.r + EPS) return 0;
    if( d1 < c.r - EPS && d2 > c.r + EPS || d1 > c.r + EPS && d2 < c.r - EPS ) return 1;
    const Point h = Projection( l, c.p);
    if( dot( l.a - h, l.b - h) < 0) return 2;
    return 0;
  }
  bool Intersect(const Circle& a,const Circle& b){
    return ( ( a.p - b.p).norm() - ( a.r + b.r) * ( a.r + b.r) < EPS) &&
      ( ( a.p - b.p).norm() - ( a.r - b.r) * ( a.r - b.r) > -EPS);
  }
  double Distance(const Segment& s,const Point& p){
    Point r = Projection(s, p);
    if ( Intersect( s, r)) return ( r - p).abs();
    return min( ( s.a - p).abs(), ( s.b - p).abs());
  }
  double Distance(const Segment& a,const Segment& b){
    if(Intersect( a, b)) return 0;
    return min( min( Distance( a, b.a), Distance( a, b.b)), min( Distance( b, a.a), Distance( b, a.b)));
  }
  double Distance(const Line& l,const Line& m) {
    return Intersect( l, m) ? 0 : Distance( l, m.a);
  }
  double Distance(const Line& l,const Segment& s) { //OK
    if (Intersect(l, s)) return 0;
    return min(Distance(l, s.a), Distance(l, s.b));
  }
  double Distance(const Point& a,const Point& b){ //OK
    return ( a - b).abs();
  }
  Point Crosspoint(const Segment& l,const Segment& m) { //OK
    double A = cross(l.b - l.a, m.b - m.a);
    double B = cross(l.b - l.a, l.b - m.a);
    if (abs(A) < EPS && abs(B) < EPS) return m.a; // same line
    return m.a + (m.b - m.a) * B / A;
  }
  PointPoint Crosspoint(const Circle& c,const Line l){
    Point hp = Projection( l, c.p), h =  hp - c.p;
    const double d2 = h.norm();
    Point v = ( l.b - l.a) * sqrt( c.r * c.r - d2) / ( l.b - l.a).abs();
    return PointPoint(hp - v, hp + v);
  }
  PointPoint Crosspoint(const Circle& c,const Segment& l) {
    Line aa = Line( l.a, l.b);
    if(Intersect(c, l) == 2) return Crosspoint(c, aa);
    PointPoint ret = Crosspoint(c, aa);
    if(dot(l.a - ret.first, l.b - ret.first) < 0) ret.second = ret.first;
    else ret.first = ret.second;
    return ret;
  }
  PointPoint Crosspoint(const Circle& c1,const Circle& c2){ //OK
    double d = (c1.p - c2.p).abs();
    double s = (c1.r + c2.r + d) / 2;
    double S = sqrt( s * ( s - c1.r) * ( s - c2.r) * ( s - d));
    double h = 2 * S / d;
    Point v = ( c2.p - c1.p) / ( c2.p - c1.p).abs();
    double m = sqrt( c1.r * c1.r - h * h);
    return PointPoint( c1.p + v * m + Point(0,1) * h * v, c1.p + v * m - Point(0,1) * h * v);
  }
  bool parallel(const Line& a,const Line& b){
    return abs(cross( a.b - a.a, b.b - b.a)) < EPS;
  }
  bool orthogonal(const Line& a,const Line& b){
    return abs(dot( a.a - a.b, b.a - b.b)) < EPS;
  }
  int Contains(const Polygon& Q,const Point& p){
    bool in = false;
    for(int i = 0 ; i < Q.size() ; i++ ){
      Point a = curr(Q,i) - p, b = next(Q,i) - p;
      if(a.y > b.y) swap(a,b);
      if(a.y <= 0 && 0 < b.y && cross(a,b) < 0) in = !in;
      if(cross(a,b) == 0 && dot(a,b) <= 0) return ON;
    }
    return in ? IN : OUT;
  }
  bool Contains(const Circle& c,const Point& p){
    return ( c.p - p).abs() < c.r + EPS;
  }
  double Area2(const Polygon& p){ //OK
    double A = 0;
    for (int i = 0; i < p.size(); ++i){
      A += cross(curr(p, i), next(p, i));
    }
    return A;
  }
  bool IsConvex(const Polygon& p){
    for(int i = 0; i < p.size(); i++){
      if(ccw(prev(p,i),curr(p,i),next(p,i)) == -1) return false;
    }
    return true;
  }
  Polygon Convex_Hull(Polygon& p){
    int n = p.size(), k = 0;
    if(n >= 3){
      sort( p.begin(), p.end());
      vector< Point > ch(2 * n);
      for(int i = 0; i < n; ch[k++] = p[i++]){
        while(k >= 2 && cross( ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < 0) --k;
      }
      for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--]){
        while(k >= t && cross( ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < 0) --k;
      }
      ch.resize( k - 1);
      return ch;
    } else {
      return p;
    }
  }
  double Convex_Diameter(Polygon& p){
    int n = p.size();
    int is = 0, js = 0;
    for(int i = 1; i < n; i++){
      if(p[i].y > p[is].y) is = i;
      if(p[i].y < p[js].y) js = i;
    }
    double maxdis = ( p[is] - p[js]).norm();
  
    int maxi, maxj, i, j;
    i = maxi = is;
    j = maxj = js;
    do {
      if(cross( next( p, i) - curr( p, i), next( p, j) - curr( p, j)) >= 0){
        j = (j + 1) % n;
      } else {
        i = (i + 1) % n;
      }
      if(( p[i] - p[j]).norm() > maxdis){
        maxdis = ( p[i] - p[j]).norm();
        maxi = i; maxj = j;
      }
    }  while (i != is || j != js);
    return maxdis;
  }
};
  
Geometory geo;
typedef Geometory::Point P;
typedef Geometory::Line L;
typedef Geometory::Segment S;
typedef Geometory::Circle C;

double Dijkstra(const P *pts, const int& size, S line){
  typedef pair< double, int > Pi;
  double min_cost[1000];
  fill_n( min_cost, size, 1e9);
  priority_queue< Pi, vector< Pi >, greater< Pi > > que;

  que.push( Pi( 0.0, 0));
  min_cost[0] = 0.0;

  while(!que.empty()){
    Pi p = que.top(); que.pop();
    if(p.second == 1) return p.first + line.abs();
    if(min_cost[p.second] < p.first) continue;
    for(int i = 0; i < size; i++){
      S l = S( pts[p.second], pts[i]);
      if(geo.Intersect(l,line) || p.first + l.abs() >= min_cost[i]) continue;
      que.push( Pi( p.first + l.abs(), i));
      min_cost[i] = p.first + l.abs();
    }
  }
  return -1;
}

int main(){
  int Na, Nb;
  P pa[1000], pb[1000];

  cin >> Na >> Nb;
  for(int i = 0; i < Na; i++){
    cin >> pa[i];
  }
  for(int i = 0; i < Nb; i++){
    cin >> pb[i];
  }
  double a = Dijkstra( pa, Na, S( pb[0], pb[1]));
  double b = Dijkstra( pb, Nb, S( pa[0], pa[1]));
  cout << fixed << setprecision(10);
  if(a == -1 && b == -1) cout << "-1" << endl;
  else if(a == -1 || b == -1) cout << max( a, b) << endl;
  else cout << min(a,b) << endl;
               
  return 0;
}
### Prompt

Your challenge is to write a cpp solution to the following problem:

The Kingdom of Neva is home to two ethnic groups, the Totata and the Tutete. The biggest feature of the Totata tribe is that they eat sweet and sour pork with pineapple. However, the Tutete tribe eats vinegared pork in pineapple. These two peoples couldn't get along with each other, and the Totata and Tutete have been in conflict for hundreds of years.

One day, a petition arrived from two ethnic groups under King Neva. According to it, the Totata tribe wants to build a road connecting the town A and the town B where they live. On the other hand, the Tutete tribe also wants to build a road connecting the town C and the town D where they live.

To prevent the two races from clashing, the roads of the Totata and Tutete cannot be crossed. Also, due to technical restrictions, it is only possible to build a road that connects the two cities in a straight line. In other words, if necessary, instead of connecting city A and city B directly with a road, it would indirectly connect city A and city B via some Totata towns (of course, of the Tutete tribe). Do not go through the city). At that time, the roads connecting the towns of the Totata tribe may intersect. The same applies to town C and town D.

Building a road costs proportional to its length. Therefore, I would like to make the total length of the roads to be constructed as short as possible while satisfying the conditions. Now, what is the minimum length?



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


The integer NA (2 ≤ NA ≤ 1,000) and the integer NB (2 ≤ NB ≤ 1,000) are written on the first line of the input, separated by blanks. This means that there are NA towns where the Totata tribe lives and NB towns where the Tutete tribe lives in the Kingdom of Neva. In the initial state, no road has been built anywhere.

The following NA line contains the integers xA, i (-10,000 ≤ xA, i ≤ 10,000) and the integers yA, i (-10,000 ≤ yA, i ≤ 10,000), separated by blanks. The geography of the Kingdom of Neva is represented by a two-dimensional Cartesian coordinate plane, and the integers xA, i and yA, i written on the 1 + i line are the position coordinates of the i-th city where the Totata tribe lives (xA, i, yA). , I). (xA, 1, yA, 1) and (xA, 2, yA, 2) are the coordinates of the two cities to be connected.

On the following NB line, the integers xB, i (-10,000 ≤ xB, i ≤ 10,000) and the integers yB, i (-10,000 ≤ yB, i ≤ 10,000) are written separated by blanks. The integers xB, i and yB, i written on the 1 + NA + i line indicate that the position coordinates of the i-th city where the Ytterbium live are (xB, i, yB, i). (xB, 1, yB, 1) and (xB, 2, yB, 2) are the coordinates of the two cities to be connected.

It can be assumed that the coordinates of the two cities are different and that none of the three cities are on the same straight line.

Output

When the road is constructed so as to meet the conditions of the problem statement, output the minimum value of the total length of the road. The "length" here is the Euclidean distance. However, if you cannot build a road that meets the conditions, output -1 instead. The output may contain errors, but the relative error to the true value must be less than 10-9.

Examples

Input

2 2
0 0
1 1
2 0
2 -1


Output

2.414213562373


Input

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


Output

-1


Input

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


Output

12.359173603117

### Response

```cpp
#include<bits/stdc++.h>
using namespace std;

/*                         */
/*                         */
/* @@ Geometory Library @@ */
/*               by ei1333 */
/*                         */
const double EPS = 1e-8, PI = acos(-1);
 
inline bool eq(double a,double b){ return abs(b - a) < EPS; }
#define curr(P,i) P[i]
#define next(P,i) P[(i+1)%P.size()]
#define prev(P,i) P[(i+P.size()-1) % P.size()]
enum { OUT, ON, IN };
struct Geometory { // Geometory Library
  struct Point {
    double x, y;
    Point(){};
    Point(double x,double y):x(x),y(y){};
    Point operator+(const Point& b) const { return Point(x + b.x,y + b.y); }
    Point operator-(const Point& b) const { return Point(x - b.x,y - b.y); }
    Point operator*(const double b) const { return Point(x * b,y * b); }
    Point operator*(const Point& b) const { return Point(x * b.x - y * b.y,x * b.y + y * b.x); }
    Point operator/(const double b) const { return Point(x / b,y / b); }
    bool operator< (const Point& b) const { return x != b.x ? x < b.x : y < b.y;}
    bool operator==(const Point& b) const { return eq(x,b.x) && eq(y,b.y); }
    double norm(){ return x * x + y * y; }
    double arg(){ return atan2(x,y); }
    double abs(){ return sqrt(norm()); }
    Point rotate(double theta){ return Point(cos(theta) * x - sin(theta) * y,sin(theta) * x + cos(theta) * y); }
    Point rotate90(){ return Point(-y,x); }
    friend ostream& operator<<(ostream& os, Point& p){ return os<<"("<<p.x<<","<<p.y<<")"; }
    friend istream& operator>>(istream& is, Point& a){ return is>>a.x>>a.y; }
  };
    
  struct Line {
    Point a, b;
    Line(){};
    Line(Point a,Point b):a(a),b(b){};
    friend ostream& operator<<(ostream& os, Line& p){ return os<<"("<<p.a.x<<","<<p.a.y<<") to ("<<p.b.x<<","<<p.b.y<<")"; }
    friend istream& operator>>(istream& is, Line& a){ return is>>a.a.x>>a.a.y>>a.b.x>>a.b.y; }
  };
  struct Segment {
    Point a, b;
    Segment(){};
    Segment(Point a,Point b):a(a),b(b){};
    friend ostream& operator<<(ostream& os, Segment& p){ return os<<"("<<p.a.x<<","<<p.a.y<<") to ("<<p.b.x<<","<<p.b.y<<")"; }
    friend istream& operator>>(istream& is, Segment& a){ return is>>a.a.x>>a.a.y>>a.b.x>>a.b.y; }
    double abs(){ return (a - b).abs(); }
  };
  struct Circle {
    Point p; double r;
    Circle(){};
    Circle(Point p, double r) : p(p),r(r){};
  };
  typedef vector< Point > Polygon;
  typedef vector< Segment > Segments;
  typedef vector< Line > Lines;
  typedef vector< Circle > Circles;
  typedef pair< Point, Point > PointPoint;
    
  double cross(const Point& a,const Point& b){
    return a.x * b.y - a.y * b.x;
  }
  double dot(const Point& a,const Point& b){
    return a.x * b.x + a.y * b.y;
  }
    
  int ccw(const Point& a,Point b,Point c){
    b = b - a, c = c - a;
    if(cross(b,c) > EPS)    return +1;  // a → b で 反時計方向におれて c
    if(cross(b,c) < -EPS)    return -1; // a → b で 時計方向におれて c
    if(dot(b,c) < 0)      return +2;  // c -- a -- bで一直線上
    if(b.norm() < c.norm()) return -2; // a -- b -- cで一直線上
    return 0;  // a -- c -- bで一直線上
  }
  Point Projection(const Line& l, const Point& p){
    double t = dot( p - l.a, l.a - l.b) / (l.a - l.b).norm();
    return l.a + (l.a - l.b) * t;
  }
  Point Projection(const Segment& l, const Point& p){
    double t = dot( p - l.a, l.a - l.b) / (l.a - l.b).norm();
    return l.a + (l.a - l.b) * t;
  }
  Point Reflection(const Line& l, const Point& p){
    return p + (Projection( l, p) - p) * 2.0;
  }
    
  double Distance( const Line& l,const Point& p) { //OK
    return (p - Projection( l, p)).abs();
  }
    
  bool Intersect(const Line& l, const Line& m){
    return abs(cross(l.b - l.a, m.b - m.a)) > EPS || abs(cross(l.b-l.a, m.b-l.a)) < EPS;
  }
  bool Intersect(const Line& l, const Segment& s){
    return cross( l.b - l.a, s.a - l.a) * cross( l.b - l.a, s.b - l.a) < EPS;
  }
  bool Intersect(const Line& l, const Point& p){
    return abs(ccw(l.a, l.b, p)) != -1;
  }
  bool Intersect(const Segment& s, const Segment& t){
    return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
  }
  bool Intersect(const Segment& s, const Point& p){
    return ccw(s.a, s.b, p) == 0;
  }
  bool Intersect(const Circle& c,const Line& l){
    return Distance( l, c.p) <= c.r + EPS;
  }
  bool Intersect(const Circle& c,const Point& p){
    return abs( ( p - c.p).abs() - c.r ) < EPS;
  }
  int Intersect(const Circle& c, const Segment& l){
    if( (Projection( l, c.p) - c.p).norm() - c.r * c.r > EPS) return 0;
    const double d1 = ( c.p - l.a).abs(), d2 = ( c.p - l.b).abs();
    if( d1 < c.r + EPS && d2 < c.r + EPS) return 0;
    if( d1 < c.r - EPS && d2 > c.r + EPS || d1 > c.r + EPS && d2 < c.r - EPS ) return 1;
    const Point h = Projection( l, c.p);
    if( dot( l.a - h, l.b - h) < 0) return 2;
    return 0;
  }
  bool Intersect(const Circle& a,const Circle& b){
    return ( ( a.p - b.p).norm() - ( a.r + b.r) * ( a.r + b.r) < EPS) &&
      ( ( a.p - b.p).norm() - ( a.r - b.r) * ( a.r - b.r) > -EPS);
  }
  double Distance(const Segment& s,const Point& p){
    Point r = Projection(s, p);
    if ( Intersect( s, r)) return ( r - p).abs();
    return min( ( s.a - p).abs(), ( s.b - p).abs());
  }
  double Distance(const Segment& a,const Segment& b){
    if(Intersect( a, b)) return 0;
    return min( min( Distance( a, b.a), Distance( a, b.b)), min( Distance( b, a.a), Distance( b, a.b)));
  }
  double Distance(const Line& l,const Line& m) {
    return Intersect( l, m) ? 0 : Distance( l, m.a);
  }
  double Distance(const Line& l,const Segment& s) { //OK
    if (Intersect(l, s)) return 0;
    return min(Distance(l, s.a), Distance(l, s.b));
  }
  double Distance(const Point& a,const Point& b){ //OK
    return ( a - b).abs();
  }
  Point Crosspoint(const Segment& l,const Segment& m) { //OK
    double A = cross(l.b - l.a, m.b - m.a);
    double B = cross(l.b - l.a, l.b - m.a);
    if (abs(A) < EPS && abs(B) < EPS) return m.a; // same line
    return m.a + (m.b - m.a) * B / A;
  }
  PointPoint Crosspoint(const Circle& c,const Line l){
    Point hp = Projection( l, c.p), h =  hp - c.p;
    const double d2 = h.norm();
    Point v = ( l.b - l.a) * sqrt( c.r * c.r - d2) / ( l.b - l.a).abs();
    return PointPoint(hp - v, hp + v);
  }
  PointPoint Crosspoint(const Circle& c,const Segment& l) {
    Line aa = Line( l.a, l.b);
    if(Intersect(c, l) == 2) return Crosspoint(c, aa);
    PointPoint ret = Crosspoint(c, aa);
    if(dot(l.a - ret.first, l.b - ret.first) < 0) ret.second = ret.first;
    else ret.first = ret.second;
    return ret;
  }
  PointPoint Crosspoint(const Circle& c1,const Circle& c2){ //OK
    double d = (c1.p - c2.p).abs();
    double s = (c1.r + c2.r + d) / 2;
    double S = sqrt( s * ( s - c1.r) * ( s - c2.r) * ( s - d));
    double h = 2 * S / d;
    Point v = ( c2.p - c1.p) / ( c2.p - c1.p).abs();
    double m = sqrt( c1.r * c1.r - h * h);
    return PointPoint( c1.p + v * m + Point(0,1) * h * v, c1.p + v * m - Point(0,1) * h * v);
  }
  bool parallel(const Line& a,const Line& b){
    return abs(cross( a.b - a.a, b.b - b.a)) < EPS;
  }
  bool orthogonal(const Line& a,const Line& b){
    return abs(dot( a.a - a.b, b.a - b.b)) < EPS;
  }
  int Contains(const Polygon& Q,const Point& p){
    bool in = false;
    for(int i = 0 ; i < Q.size() ; i++ ){
      Point a = curr(Q,i) - p, b = next(Q,i) - p;
      if(a.y > b.y) swap(a,b);
      if(a.y <= 0 && 0 < b.y && cross(a,b) < 0) in = !in;
      if(cross(a,b) == 0 && dot(a,b) <= 0) return ON;
    }
    return in ? IN : OUT;
  }
  bool Contains(const Circle& c,const Point& p){
    return ( c.p - p).abs() < c.r + EPS;
  }
  double Area2(const Polygon& p){ //OK
    double A = 0;
    for (int i = 0; i < p.size(); ++i){
      A += cross(curr(p, i), next(p, i));
    }
    return A;
  }
  bool IsConvex(const Polygon& p){
    for(int i = 0; i < p.size(); i++){
      if(ccw(prev(p,i),curr(p,i),next(p,i)) == -1) return false;
    }
    return true;
  }
  Polygon Convex_Hull(Polygon& p){
    int n = p.size(), k = 0;
    if(n >= 3){
      sort( p.begin(), p.end());
      vector< Point > ch(2 * n);
      for(int i = 0; i < n; ch[k++] = p[i++]){
        while(k >= 2 && cross( ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < 0) --k;
      }
      for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = p[i--]){
        while(k >= t && cross( ch[k - 1] - ch[k - 2], p[i] - ch[k - 1]) < 0) --k;
      }
      ch.resize( k - 1);
      return ch;
    } else {
      return p;
    }
  }
  double Convex_Diameter(Polygon& p){
    int n = p.size();
    int is = 0, js = 0;
    for(int i = 1; i < n; i++){
      if(p[i].y > p[is].y) is = i;
      if(p[i].y < p[js].y) js = i;
    }
    double maxdis = ( p[is] - p[js]).norm();
  
    int maxi, maxj, i, j;
    i = maxi = is;
    j = maxj = js;
    do {
      if(cross( next( p, i) - curr( p, i), next( p, j) - curr( p, j)) >= 0){
        j = (j + 1) % n;
      } else {
        i = (i + 1) % n;
      }
      if(( p[i] - p[j]).norm() > maxdis){
        maxdis = ( p[i] - p[j]).norm();
        maxi = i; maxj = j;
      }
    }  while (i != is || j != js);
    return maxdis;
  }
};
  
Geometory geo;
typedef Geometory::Point P;
typedef Geometory::Line L;
typedef Geometory::Segment S;
typedef Geometory::Circle C;

double Dijkstra(const P *pts, const int& size, S line){
  typedef pair< double, int > Pi;
  double min_cost[1000];
  fill_n( min_cost, size, 1e9);
  priority_queue< Pi, vector< Pi >, greater< Pi > > que;

  que.push( Pi( 0.0, 0));
  min_cost[0] = 0.0;

  while(!que.empty()){
    Pi p = que.top(); que.pop();
    if(p.second == 1) return p.first + line.abs();
    if(min_cost[p.second] < p.first) continue;
    for(int i = 0; i < size; i++){
      S l = S( pts[p.second], pts[i]);
      if(geo.Intersect(l,line) || p.first + l.abs() >= min_cost[i]) continue;
      que.push( Pi( p.first + l.abs(), i));
      min_cost[i] = p.first + l.abs();
    }
  }
  return -1;
}

int main(){
  int Na, Nb;
  P pa[1000], pb[1000];

  cin >> Na >> Nb;
  for(int i = 0; i < Na; i++){
    cin >> pa[i];
  }
  for(int i = 0; i < Nb; i++){
    cin >> pb[i];
  }
  double a = Dijkstra( pa, Na, S( pb[0], pb[1]));
  double b = Dijkstra( pb, Nb, S( pa[0], pa[1]));
  cout << fixed << setprecision(10);
  if(a == -1 && b == -1) cout << "-1" << endl;
  else if(a == -1 || b == -1) cout << max( a, b) << endl;
  else cout << min(a,b) << endl;
               
  return 0;
}
```