Problem:
Traveling Salesperson in an Island
You are a salesperson at one of the ports in an island. You have to visit all the ports of the island and then come back to the starting port. Because you cannot swim and are scared of the sea, you have to stay on the land during your journey.
The island is modeled as a polygon on a two-dimensional plane. The polygon is
simple
, that is, its vertices are distinct and no two edges intersect or touch, other than consecutive edges which touch at their common vertex. In addition, no two consecutive edges are collinear. Each port in the island is modeled as a point on the boundary of the polygon. Your route is modeled as a closed curve that does not go outside of the polygon.
In preparation for the journey, you would like to compute the minimum length of a route to visit all the ports and return to the starting port.
Input
The input consists of a single test case of the following format.
$n$ $m$
$x_1$ $y_1$
.
.
.
$x_n$ $y_n$
$x'_1$ $y'_1$
.
.
.
$x'_m$ $y'_m$
The first line contains two integers $n$ and $m$, which satisfy $3 \leq n \leq 100$ and $2 \leq m \leq 100$.
Here, $n$ is the number of vertices of the polygon modeling the island, and $m$ is the number of the ports in the island. Each of the next $n$ lines consists of two integers $x_i$ and $y_i$, which are the coordinates of the $i$-th vertex of the polygon, where $0 \leq x_i \leq 1000$ and $0 \leq y_i \leq 1000$. The vertices of the polygon are given in counterclockwise order. Each of the $m$ following lines consists of two integers $x'_j$ and $y'_j$, which are the coordinates of the $j$-th port. The route starts and ends at ($x'_1, y'_1$). It is guaranteed that all the ports are on the boundary of the polygon and pairwise distinct.
Output
Output in a line the minimum length of a route to visit all the ports and return to the starting port. The relative error of the output must be within $10^{−6}$.
Sample Input 1
4 4
0 0
2 0
2 2
0 2
1 0
1 2
2 1
0 1
Sample Output 1
5.656854249492381
Sample Input 2
8 2
0 0
4 0
4 4
0 4
0 3
3 3
3 1
0 1
0 0
0 4
Sample Output 2
16.64911064067352
These samples are depicted in the following figures. The shortest routes are depicted by the thick lines. The gray polygons represent the islands. The small disks represent the ports in the islands. Note that the route does not have to be simple, i.e., the route may intersect or overlap itself as in the second sample, in which the same path between the two ports is used twice.
Figure J.1.  Sample 1
Figure J.2. Sample 2

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define vi vector<int>
#define vl vector<ll>
#define vii vector<pair<int,int>>
#define vll vector<pair<ll,ll>>
#define vvi vector<vector<int>>
#define vvl vector<vector<ll>>
#define vvii vector<vector<pair<int,int>>>
#define vvll vector<vector<pair<ll,ll>>>
#define vst vector<string>
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define mkunique(x) sort(all(x));(x).erase(unique(all(x)),(x).end())
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=998244353,MAX=205,INF=15<<26;

//幾何ライブラリ
// define double ll をするときは Point の < と == も書き換えよう！

const double eps=1e-8;
const double pi=acos((double)-1.0L);
#define equals(a,b) (fabs((a)-(b))<eps)

double torad(double deg) {return (double)(deg)*pi/180.0;}
double todeg(double ang) {return ang*180.0/pi;}

class Point{
public:
    double x,y;
    
    Point(double x=0,double y=0):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);}
    
    double abs(){return sqrt(norm());}
    double norm(){return x*x+y*y;}
    
    bool operator < (const Point &p)const{
        return x+eps<p.x||(equals(x,p.x)&&y+eps<p.y);
        //return x<p.x||(x==p.x&&y<p.y);
    }
    
    bool operator == (const Point &p)const{
        return fabs(x-p.x)<eps/100000&&fabs(y-p.y)<eps/100000;
        //return x==p.x&&y==p.y;
    }
};

typedef Point Vector;

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

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

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

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

struct Segment{
    Point p1,p2;
};

bool isOrthogonal(Vector a,Vector b){
    return equals(dot(a,b),0.0);
}

bool isOrthogonal(Point a1,Point a2,Point b1,Point b2){
    return isOrthogonal(a1-a2,b1-b2);
}

bool isOrthogonal(Segment s1,Segment s2){
    return equals(dot(s1.p2-s1.p1,s2.p2-s2.p1),0.0);
}

bool isParallel(Vector a,Vector b){
    return equals(cross(a,b),0.0);
}

bool isParallel(Point a1,Point a2,Point b1,Point b2){
    return isParallel(a1-a2,b1-b2);
}

bool isParallel(Segment s1,Segment s2){
    return equals(cross(s1.p2-s1.p1,s2.p2-s2.p1),0.0);
}

Point project(Segment s,Point p){
    Vector base=s.p2-s.p1;
    double r=dot(p-s.p1,base)/norm(base);
    return s.p1+base*r;
}

Point reflect(Segment s,Point p){
    return p+(project(s,p)-p)*2.0;
}

Point turn(Point p,Point c,double pi){
    double q=atan2(p.y-c.y,p.x-c.x);
    q+=pi;
    p=c+Point{cos(q)*abs(p-c),sin(q)*abs(p-c)};
    
    return p;
}
//pをcを中心としてpi回転させる(1周で2π)
//p=cのときnan

//p0,p1,p2の順に見たときどうなるか？

static const int counter_clockwise=1;
static const int clockwise=-1;
static const int online_back=2;
static const int online_front=-2;
static const int on_segment=0;

int ccw(Point p0,Point p1,Point p2){
    Vector a=p1-p0;
    Vector 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(a.norm()<b.norm()) return online_front;
    
    return on_segment;
}

bool intersect(Point p1,Point p2,Point p3,Point p4){
    return(ccw(p1,p2,p3)*ccw(p1,p2,p4)<0&&ccw(p3,p4,p1)*ccw(p3,p4,p2)<0);
}

bool intersect(Segment s1,Segment s2){
    return intersect(s1.p1,s1.p2,s2.p1,s2.p2);
}

bool overlap(Segment s1,Segment s2){
    int a=ccw(s1.p1,s1.p2,s2.p1),b=ccw(s1.p1,s1.p2,s2.p2);
    if(a&1||b&1) return 0;
    if(a==2){
        if(b==-2||(b==0&&!(s2.p2==s1.p1))) return 1;
        else return 0;
    }
    if(a==-2){
        if(b==2||(b==0&&!(s2.p2==s1.p2))) return 1;
        else return 0;
    }
    if(a==0){
        if(s1.p1==s2.p1){
            if(b!=2) return 1;
            else return 0;
        }
        else if(s1.p2==s2.p1){
            if(b!=-2) return 1;
            else return 0;
        }
        else return 1;
    }
    return 0;
}
//s1とs2の共通の線分(長さ0より大きい)があるかどうか

typedef Segment Line;

double getDistance(Point a,Point b){
    return abs(a-b);
}

double getDistanceLP(Line l,Point p){
    return abs(cross(l.p2-l.p1,p-l.p1)/abs(l.p2-l.p1));
}

double getDistanceSP(Segment s,Point p){
    if(dot(s.p2-s.p1,p-s.p1)<0.0) return abs(p-s.p1);
    if(dot(s.p1-s.p2,p-s.p2)<0.0) return abs(p-s.p2);
    return getDistanceLP(s,p);
}

double getDistance(Segment s1,Segment s2){
    if(intersect(s1,s2)) return 0.0;
    return min({getDistanceSP(s1,s2.p1),getDistanceSP(s1,s2.p2),getDistanceSP(s2,s1.p1),getDistanceSP(s2,s1.p2)});
}

Point getCrossPointS(Segment s1,Segment s2){
    //if(ccw(s1.p1,s1.p2,s2.p1)==0&&ccw(s1.p1,s1.p2,s2.p2)==0) return s1.p1;
    Vector base=s2.p2-s2.p1;
    double d1=abs(cross(base,s1.p1-s2.p1));
    double d2=abs(cross(base,s1.p2-s2.p1));
    double t=d1/(d1+d2);
    return s1.p1+(s1.p2-s1.p1)*t;
}//同じ時壊れます

Point getCrossPointL(Line l1,Line l2){
    //if(ccw(s1.p1,s1.p2,s2.p1)==0&&ccw(s1.p1,s1.p2,s2.p2)==0) return s1.p1;
    
    Vector v1=l1.p2-l1.p1,v2=l2.p2-l2.p1;
    
    return l1.p1+v1*cross(v2,l2.p1-l1.p1)/cross(v2,v1);
}

Segment ParallelSegment(Segment s,double d){
    Vector v={-(s.p2-s.p1).y,(s.p2-s.p1).x};
    v=v/abs(v);
    
    s.p1=s.p1+v*d;
    s.p2=s.p2+v*d;
    
    return s;
}

Point naisin(Point p1,Point p2,Point p3){
    if(p1==p2&&p2==p3&&p3==p1) return p1;
    
    return (p1*abs(p2-p3)+p2*abs(p1-p3)+p3*abs(p1-p2))/(abs(p2-p3)+abs(p1-p3)+abs(p1-p2));
}

Point naisin(Line l1,Line l2,Line l3){
    //平行でない前提
    
    Point p1=getCrossPointL(l1,l2),p2=getCrossPointL(l1,l3),p3=getCrossPointL(l2,l3);
    return naisin(p1,p2,p3);
}

//ネットの適当を書いたのであってるか全く知りません→あってそう

class Circle{
public:
    Point c;
    double r;
    Circle(Point c=Point(),double r=0.0):c(c),r(r){}
};

Point CircleCenter(Point a,Point b,Point c){
    Point u=a-b,v=a-c;
    double m1=(norm(a)-norm(b))/2.0,m2=(norm(a)-norm(c))/2.0;
    
    Point res;
    if(cross(u,v)==0.0){
        res.x=1e9;
        res.y=1e9;
        
        return res;
    }
    res.x=(m1*v.y-m2*u.y)/cross(u,v);
    res.y=(m1*v.x-m2*u.x)/cross(v,u);
    
    return res;
}
//3点を通る円の中心を返す

//交わる 0
// c1がc2のinside 1
// c1がc2のoutside 2
// 交わらない 3

int not_intersect(Circle c1,Circle c2){
    double d=getDistance(c1.c,c2.c);
    double r1=c1.r,r2=c2.r;
    if(r1<r2){
        if(d<(r2-r1)) return 1;
    }
    if(r1>r2){
        if(d<(r1-r2)) return 2;
    }
    if(d<=r1+r2) return 0;
    else return 3;
}

pair<Point,Point> segCrossPpoints(Circle c,Line l){
    //assert(intersect(c,l));
    Vector pr=project(l,c.c);
    Vector e=(l.p2-l.p1)/abs(l.p2-l.p1);
    double base=sqrt(c.r*c.r-norm(pr-c.c));
    return make_pair(pr+e*base,pr-e*base);
}

double arg(Vector p){return atan2(p.y,p.x);}
Vector polar(double a,double r){return Point(cos(r)*a,sin(r)*a);}

//inside(outside)

pair<Point,Point> getCrossPoints(Circle c1,Circle c2){
    //assert(intersect(c1,c2));
    double d=abs(c1.c-c2.c);
    double a=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));
    double t=arg(c2.c-c1.c);
    return make_pair(c1.c+polar(c1.r,t+a),c1.c+polar(c1.r,t-a));
}

vector<Line> Commontangent(Circle c1,Circle c2){
    vector<Line> res;
    Point p=c2.c-c1.c;
    
    if(abs(p)>=(c1.r+c2.r)){
        Point a,b;
        a.x=c1.r*(p.x*(c1.r+c2.r)+p.y*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
        a.y=c1.r*(p.y*(c1.r+c2.r)-p.x*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
        
        b.x=c1.r*(p.x*(c1.r+c2.r)-p.y*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
        b.y=c1.r*(p.y*(c1.r+c2.r)+p.x*sqrt(norm(p)-(c1.r+c2.r)*(c1.r+c2.r)))/norm(p);
        
        res.push_back(Line{a+c1.c,a+c1.c+Point{-a.y,a.x}});
        if(!(a==b)){
            res.push_back(Line{b+c1.c,b+c1.c+Point{-b.y,b.x}});
        }
    }
    
    if(abs(p)>=abs(c1.r-c2.r)){
        Point a,b;
        a.x=c1.r*(p.x*(c1.r-c2.r)+p.y*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
        a.y=c1.r*(p.y*(c1.r-c2.r)-p.x*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
        
        b.x=c1.r*(p.x*(c1.r-c2.r)-p.y*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
        b.y=c1.r*(p.y*(c1.r-c2.r)+p.x*sqrt(norm(p)-(c1.r-c2.r)*(c1.r-c2.r)))/norm(p);
        
        res.push_back(Line{a+c1.c,a+c1.c+Point{-a.y,a.x}});
        if(!(a==b)){
            res.push_back(Line{b+c1.c,b+c1.c+Point{-b.y,b.x}});
        }
    }
    
    return res;
}

typedef vector<Point> Polygon;

/*
 IN 2
 ON 1
 OUT 0
 */

int contains(Polygon g,Point p){
    int n=int(g.size());
    bool x=false;
    for(int i=0;i<n;i++){
        Point a=g[i]-p,b=g[(i+1)%n]-p;
        if(a.y>b.y) swap(a,b);
        if(a.y<eps&&0<b.y&&cross(a,b)<0) x=!x;
        if(abs(cross(a,b))<eps&&dot(a,b)<eps) return 1;
    }
    return (x?2:0);
}

Polygon andrewScan(Polygon s,bool ok){
    Polygon u,l;
    sort(all(s));
    
    if(int(s.size())<3) return s;
    int n=int(s.size());
    
    u.push_back(s[0]);
    u.push_back(s[1]);
    
    l.push_back(s[n-1]);
    l.push_back(s[n-2]);
    
    if(ok){
        for(int i=2;i<n;i++){
            for(int j=int(u.size());j>=2&&ccw(u[j-2],u[j-1],s[i])==counter_clockwise;j--){
                u.pop_back();
            }
            u.push_back(s[i]);
        }
        
        for(int i=int(s.size())-3;i>=0;i--){
            for(int j=int(l.size());j>=2&&ccw(l[j-2],l[j-1],s[i])==counter_clockwise;j--){
                l.pop_back();
            }
            l.push_back(s[i]);
        }
    }
    
    if(!ok){
        for(int i=2;i<n;i++){
            for(int j=int(u.size());j>=2&&ccw(u[j-2],u[j-1],s[i])!=clockwise;j--){
                u.pop_back();
            }
            u.push_back(s[i]);
        }
        
        for(int i=int(s.size())-3;i>=0;i--){
            for(int j=int(l.size());j>=2&&ccw(l[j-2],l[j-1],s[i])!=clockwise;j--){
                l.pop_back();
            }
            l.push_back(s[i]);
        }
    }
    
    reverse(all(l));
    
    for(int i=int(u.size())-2;i>=1;i--) l.push_back(u[i]);
    
    return l;
}//ok==1なら辺の上も含める

Polygon convex_cut(const Polygon& P, const Line& l) {
    Polygon Q;
    for(int i=0;i<si(P);i++){
        Point A=P[i],B=P[(i+1)%si(P)];
        if(ccw(l.p1,l.p2,A)!=-1)Q.push_back(A);
        if(ccw(l.p1,l.p2,A)*ccw(l.p1,l.p2,B)<0) Q.push_back(getCrossPointL(Line{A,B},l));
    }
    return Q;
}

double area(Point a,Point b,Point c){
    b=b-a;
    c=c-a;
    return abs(b.x*c.y-b.y*c.x)/2.0;
}

/*
 
 ll area(Polygon P){
 ll sum=0;
 for(int i=0;i<si(P);i++){
 sum+=cross(P[i],P[(i+1)%si(P)]);
 }
 return abs(sum);
 }
 
 */

// 倍

double area(Polygon &P){
    if(si(P)==0) return 0.0;
    double res=0;
    Point c={0.0,0.0};
    for(int i=0;i<si(P);i++){
        c=c+P[i];
    }
    c=c/si(P);
    
    for(int i=0;i<si(P);i++){
        res+=area(c,P[i],P[(i+1)%si(P)]);
    }
    
    return res;
}

ll gcd(ll a,ll b){
    if(b==0) return a;
    return gcd(b,a%b);
}

pair<Point,Vector> perpendicular_bisector(Point a,Point b){
    Point c=(a+b)/2;
    Vector v=b-c;
    swap(v.x,v.y);
    v.x*=-1;
    
    Point p=c;
    if(v.x==0){
        v.y=1;
        p.y=0;
    }
    else if(v.y==0){
        v.x=1;
        p.x=0;
    }
    else{
        if(v.x<0){
            v.x*=-1;
            v.y*=-1;
        }
        ll g=gcd(abs(ll(v.x)),abs(ll(v.y)));
        v.x/=g;
        v.y/=g;
        if(p.x>=0){
            ll d=p.x/v.x;
            p=p-v*d;
        }else{
            ll d=abs(p.x)/v.x;
            p=p+v*d;
            
            if(p.x<0){
                p=p+v;
            }
        }
    }
    
    return mp(p,v);
}
//2倍するなりして整数にしておくこと

/*
 Line perpendicular_bisector(Point a,Point b){
 Point c=(a+b)/2;
 Point d=turn(a,c,M_PI/2.0);
 
 return {c,d};
 }
 //2倍するなりして整数にしておくこと
 */
pair<Line,Line> angle_bisector(Line a,Line b){
    // assert(!isParallel(a,b));
    
    Point p=getCrossPointL(a,b);
    
    if(a.p1==p) swap(a.p1,a.p2);
    if(b.p1==p) swap(b.p1,b.p2);
    
    double kaku1=arg(a.p1-p);
    double kaku2=arg(b.p1-p);
    
    return mp(Line{p,p+polar(1.0,(kaku1+kaku2)/2.0)},Line{p,p+polar(1.0,(kaku1+kaku2+M_PI)/2.0)});
    
}


Line abc_to_line(double a,double b,double c){
    if(a==0){
        if(b==0){
            if(c>=0){
                return {{-INF,-INF},{INF,-INF}};
            }else{
                return {{-INF,INF},{INF,INF}};
            }
        }else if(b>0){
            return {{0,-c/b},{1,-c/b}};
        }else{
            return {{1,-c/b},{0,-c/b}};
        }
    }else if(a>0){
        if(b==0){
            return {{-c/a,1},{-c/a,0}};
        }else{
            if(b>0){
                return {{0,-c/b},{1,-(a+c)/b}};
            }else{
                return {{1,-(a+c)/b},{0,-c/b}};
            }
        }
    }else{
        if(b==0){
            return {{-c/a,0},{-c/a,1}};
        }else{
            if(b>0){
                return {{0,-c/b},{1,-(a+c)/b}};
            }else{
                return {{1,-(a+c)/b},{0,-c/b}};
            }
        }
    }
}

// ax+by+c>=0 convex_cut用の2点
// a=b=0のときは雑にINF

double dis[MAX][MAX];

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
    
    auto rd=[&](ll momo){
        ll x=rng()%momo;
        if(x<0) x+=momo;
        return x;
    };
    
    int N,M;cin>>N>>M;
    vector<Point> P(N);
    for(int i=0;i<N;i++){
        cin>>P[i].x>>P[i].y;
    }
    vector<pair<Point,pair<int,double>>> QQ(M);
    for(int i=0;i<M;i++){
        Point A;cin>>A.x>>A.y;
        for(int j=0;j<N;j++){
            if(P[j]==A){
                QQ[i].se=mp(j,0);
                break;
            }
            if(P[(j+1)%N]==A){
                QQ[i].se=mp(j,1);
                break;
            }
            if(ccw(P[j],P[(j+1)%N],A)==0){
                QQ[i].se=mp(j,abs(A-P[j])/abs(P[j]-P[(j+1)%N]));
                break;
            }
        }
        QQ[i].fi=A;
    }
    sort(all(QQ),[&](auto a,auto b){
        return a.se<b.se;
    });
    
    vector<Point> Q;
    for(auto a:QQ) Q.pb(a.fi);
    
    vector<Point> S;
    for(int i=0;i<si(P);i++){
        S.pb(P[i]);
    }
    for(int i=0;i<si(Q);i++){
        S.pb(Q[i]);
    }
    for(int i=0;i<si(S);i++){
        for(int j=0;j<si(S);j++){
            dis[i][j]=1e9;
        }
    }
    
    for(int i=0;i<si(S);i++){
        for(int j=0;j<si(S);j++){
            if(S[i]==S[j]){
                dis[i][j]=0;
                continue;
            }
            bool f=true;
            for(int a=0;a<N;a++){
                if(intersect(P[a],P[(a+1)%N],S[i],S[j])) f=false;
            }
            if(!f) continue;
            bool mita=false;
            
            for(int a=0;a<N;a++){
                if(ccw(P[a],P[(a+1)%N],S[i])==0&&ccw(P[a],P[(a+1)%N],S[j])==0){
                    mita=true;
                    dis[i][j]=abs(S[i]-S[j]);
                }
            }
            if(mita) continue;
            
            for(int a=0;a<N;a++){
                if(P[a]==S[i]||P[(a+1)%N]==S[i]) continue;
                if(ccw(P[a],P[(a+1)%N],S[i])==0&&abs(ccw(P[a],P[(a+1)%N],S[j]))%2==0) f=false;
            }
            for(int a=0;a<N;a++){
                if(P[a]==S[j]||P[(a+1)%N]==S[j]) continue;
                if(ccw(P[a],P[(a+1)%N],S[j])==0&&abs(ccw(P[a],P[(a+1)%N],S[i]))%2==0) f=false;
            }
            
            if(!f) continue;
            
            Point A=(S[i]+S[j])/2;
            double muki=acosl(-1.0l)*2*rd(mod)/mod;
            Point B=A;
            B.x+=10000*cos(muki);
            B.y+=10000*sin(muki);
            int cn=0;
            
            for(int a=0;a<N;a++){
                if(intersect(P[a],P[(a+1)%N],A,B)) cn++;
            }
            
            if(cn%2==0) f=false;
            
            if(f){
                dis[i][j]=abs(S[i]-S[j]);
            }
        }
    }
    
    for(int k=0;k<si(S);k++){
        for(int i=0;i<si(S);i++){
            for(int j=0;j<si(S);j++){
                chmin(dis[i][j],dis[i][k]+dis[k][j]);
            }
        }
    }
    
    double ans=0;
    
    for(int i=0;i<M;i++){
        ans+=dis[N+i][N+(i+1)%M];
    }
    cout<<fixed<<setprecision(25)<<ans<<endl;
}
accuracy: 1
time_ms: 50
memory_kb: 4088
final_rank: 6

code_snippet: #ifdef NACHIA
#define _GLIBCXX_DEBUG
#endif

#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <queue>
#include <cmath>
using namespace std;
using ll = long long;
template<class A, class B> void chmax(A& a, const B& b){ if(a < b) a = b; }
template<class A, class B> void chmin(A& a, const B& b){ if(b < a) a = b; }
using PLL = pair<ll, ll>;
#define rep(i,n) for(ll i=0; i<ll(n); i++)

const ll INF = 1001001001001001001;

struct Vec2 {
    ll x = 0, y = 0;
    friend Vec2 operator+(Vec2 l, Vec2 r){ return { l.x + r.x, l.y + r.y }; }
    friend Vec2 operator-(Vec2 l, Vec2 r){ return { l.x - r.x, l.y - r.y }; }
    friend bool operator==(Vec2 l, Vec2 r){ return l.x == r.x && l.y == r.y; }
    ll dot(Vec2 r) const { return x * r.x + y * r.y; }
    ll cross(Vec2 r) const { return x * r.y - y * r.x; }
};

bool dointersecth(Vec2 a, Vec2 b, Vec2 c, Vec2 d){
    ll adir = (d-c).cross(a-c);
    ll bdir = (d-c).cross(b-c);
    if(adir > 0 && bdir > 0) return false;
    if(adir < 0 && bdir < 0) return false;
    if(adir == 0 && bdir == 0){
        rep(q,2){
            if((b-a).dot(c-a) < 0 && (b-a).dot(d-a) < 0) return false;
            swap(a,b);
        }
    }
    return true;
}

bool dointersect(Vec2 a, Vec2 b, Vec2 c, Vec2 d){
    return dointersecth(a,b,c,d) && dointersecth(c,d,a,b);
}

void testcase(){
    ll N, M; cin >> N >> M;
    vector<Vec2> A(N+1);
    vector<ll> I(N+1);
    rep(i,N) cin >> A[i].x >> A[i].y;
    A[N] = A[0];
    rep(i,M){
        Vec2 a; cin >> a.x >> a.y;
        bool done = false;
        rep(j,A.size()) if(A[j] == a){
            I[j] = 1;
            done = true;
        }
        if(!done)rep(j,A.size()-1){
            if(
                (A[j+1] - A[j]).dot(a - A[j]) >= 0 &&
                (A[j] - A[j+1]).dot(a - A[j+1]) >= 0 &&
                (A[j+1] - A[j]).cross(a - A[j]) == 0
            ){
                A.insert(A.begin() + j + 1, a);
                I.insert(I.begin() + j + 1, 1);
                done = true;
                break;
            }
        }
    }
    //for(auto [u,v] : A){ cout << u << "," << v << " "; } cout << endl;
    vector<ll> Idx; rep(i,I.size()) if(I[i]) Idx.push_back(i);
    Idx.push_back(Idx.front());
    N = A.size() - 1;
    vector<vector<double>> dist(N, vector<double>(N,1e100));
    rep(i,N) dist[i][i] = 0;
    rep(a,N) rep(b,N) if(a < b){
        bool ok = true;
        rep(f,N) if(f != a && f != b && (f+1)%N != a && (f+1)%N != b){
            if(dointersect(A[a], A[b], A[f], A[f+1])){ ok = false; break; }
        }
        rep(ff,2){
            ll xa = (a == 0 ? N-1 : a-1);
            ll ya = (a == N-1 ? 0 : a+1);
            if((A[ya] - A[a]).cross(A[xa] - A[a]) > 0){
                if((A[ya] - A[a]).cross(A[b] - A[a]) < 0) ok = false;
                if((A[xa] - A[a]).cross(A[b] - A[a]) > 0) ok = false;
            } else {
                if((A[ya] - A[a]).cross(A[b] - A[a]) < 0 &&
                   (A[xa] - A[a]).cross(A[b] - A[a]) > 0) ok = false;
            }
            swap(a,b);
        }
        //if(ok){ cout << a << " " << b << endl; }
        if(ok){
            double d = sqrt(double((A[b]-A[a]).dot(A[b]-A[a])));
            dist[a][b] = d;
            dist[b][a] = d;
        }
    }
    rep(j,N) rep(i,N) rep(k,N) chmin(dist[i][k], dist[i][j] + dist[j][k]);
    //rep(i,N){
    //    cout.precision(3); cout<<fixed;
    //    rep(j,N){
    //        if(dist[i][j] > 1.0e50){ cout << "----- "; } else cout << dist[i][j] << " ";
    //    } cout << endl;
    //}
    double ans = 0;
    rep(i,Idx.size()-1) ans += dist[Idx[i]%N][Idx[i+1]%N];
    cout.precision(20);
    cout << fixed;
    cout << ans << "\n";
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    #ifdef NACHIA
    ll T; cin >> T; rep(t,T){
    #endif
    testcase();
    
    #ifdef NACHIA
    cout << "---------------------" << endl; }
    #endif
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3656
final_rank: 1

code_snippet: #ifdef NACHIA
#define _GLIBCXX_DEBUG
#endif

#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <queue>
#include <cmath>
using namespace std;
using ll = long long;
template<class A, class B> void chmax(A& a, const B& b){ if(a < b) a = b; }
template<class A, class B> void chmin(A& a, const B& b){ if(b < a) a = b; }
using PLL = pair<ll, ll>;
#define rep(i,n) for(ll i=0; i<ll(n); i++)

const ll INF = 1001001001001001001;

struct Vec2 {
    ll x = 0, y = 0;
    friend Vec2 operator+(Vec2 l, Vec2 r){ return { l.x + r.x, l.y + r.y }; }
    friend Vec2 operator-(Vec2 l, Vec2 r){ return { l.x - r.x, l.y - r.y }; }
    friend bool operator==(Vec2 l, Vec2 r){ return l.x == r.x && l.y == r.y; }
    ll dot(Vec2 r) const { return x * r.x + y * r.y; }
    ll cross(Vec2 r) const { return x * r.y - y * r.x; }
};

bool dointersecth(Vec2 a, Vec2 b, Vec2 c, Vec2 d){
    ll adir = (d-c).cross(a-c);
    ll bdir = (d-c).cross(b-c);
    if(adir > 0 && bdir > 0) return false;
    if(adir < 0 && bdir < 0) return false;
    if(adir == 0 && bdir == 0){
        rep(q,2){
            if((b-a).dot(c-a) < 0 && (b-a).dot(d-a) < 0) return false;
            swap(a,b);
        }
    }
    return true;
}

bool dointersect(Vec2 a, Vec2 b, Vec2 c, Vec2 d){
    return dointersecth(a,b,c,d) && dointersecth(c,d,a,b);
}

void testcase(){
    ll N, M; cin >> N >> M;
    vector<Vec2> A(N+1);
    vector<ll> I(N+1);
    rep(i,N) cin >> A[i].x >> A[i].y;
    A[N] = A[0];
    rep(i,M){
        Vec2 a; cin >> a.x >> a.y;
        bool done = false;
        rep(j,A.size()) if(A[j] == a){
            I[j] = 1;
            done = true;
        }
        if(!done)rep(j,A.size()-1){
            if(
                (A[j+1] - A[j]).dot(a - A[j]) >= 0 &&
                (A[j] - A[j+1]).dot(a - A[j+1]) >= 0 &&
                (A[j+1] - A[j]).cross(a - A[j]) == 0
            ){
                A.insert(A.begin() + j + 1, a);
                I.insert(I.begin() + j + 1, 1);
                done = true;
                break;
            }
        }
    }
    //for(auto [u,v] : A){ cout << u << "," << v << " "; } cout << endl;
    vector<ll> Idx; rep(i,I.size()) if(I[i]) Idx.push_back(i);
    Idx.push_back(Idx.front());
    N = A.size() - 1;
    vector<vector<double>> dist(N, vector<double>(N,1e100));
    rep(i,N) dist[i][i] = 0;
    rep(a,N) rep(b,N) if(a < b){
        bool ok = true;
        rep(f,N) if(f != a && f != b && (f+1)%N != a && (f+1)%N != b){
            if(dointersect(A[a], A[b], A[f], A[f+1])){ ok = false; break; }
        }
        rep(ff,2){
            ll xa = (a == 0 ? N-1 : a-1);
            ll ya = (a == N-1 ? 0 : a+1);
            if((A[ya] - A[a]).cross(A[xa] - A[a]) > 0){
                if((A[ya] - A[a]).cross(A[b] - A[a]) < 0) ok = false;
                if((A[xa] - A[a]).cross(A[b] - A[a]) > 0) ok = false;
            } else {
                if((A[ya] - A[a]).cross(A[b] - A[a]) < 0 &&
                   (A[xa] - A[a]).cross(A[b] - A[a]) > 0) ok = false;
            }
            swap(a,b);
        }
        //if(ok){ cout << a << " " << b << endl; }
        if(ok){
            double d = sqrt(double((A[b]-A[a]).dot(A[b]-A[a])));
            dist[a][b] = d;
            dist[b][a] = d;
        }
    }
    rep(j,N) rep(i,N) rep(k,N) chmin(dist[i][k], dist[i][j] + dist[j][k]);
    //rep(i,N){
    //    cout.precision(3); cout<<fixed;
    //    rep(j,N){
    //        if(dist[i][j] > 1.0e50){ cout << "----- "; } else cout << dist[i][j] << " ";
    //    } cout << endl;
    //}
    double ans = 0;
    rep(i,Idx.size()-1) ans += dist[Idx[i]%N][Idx[i+1]%N];
    cout.precision(20);
    cout << fixed;
    cout << ans << "\n";
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    #ifdef NACHIA
    ll T; cin >> T; rep(t,T){
    #endif
    testcase();
    
    #ifdef NACHIA
    cout << "---------------------" << endl; }
    #endif
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3724
final_rank: 2

code_snippet: #ifdef NACHIA
#define _GLIBCXX_DEBUG
#endif

#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <queue>
#include <cmath>
using namespace std;
using ll = long long;
template<class A, class B> void chmax(A& a, const B& b){ if(a < b) a = b; }
template<class A, class B> void chmin(A& a, const B& b){ if(b < a) a = b; }
using PLL = pair<ll, ll>;
#define rep(i,n) for(ll i=0; i<ll(n); i++)

const ll INF = 1001001001001001001;

struct Vec2 {
    ll x = 0, y = 0;
    friend Vec2 operator+(Vec2 l, Vec2 r){ return { l.x + r.x, l.y + r.y }; }
    friend Vec2 operator-(Vec2 l, Vec2 r){ return { l.x - r.x, l.y - r.y }; }
    friend bool operator==(Vec2 l, Vec2 r){ return l.x == r.x && l.y == r.y; }
    ll dot(Vec2 r) const { return x * r.x + y * r.y; }
    ll cross(Vec2 r) const { return x * r.y - y * r.x; }
};

bool dointersecth(Vec2 a, Vec2 b, Vec2 c, Vec2 d){
    ll adir = (d-c).cross(a-c);
    ll bdir = (d-c).cross(b-c);
    if(adir > 0 && bdir > 0) return false;
    if(adir < 0 && bdir < 0) return false;
    return true;
}

bool dointersect(Vec2 a, Vec2 b, Vec2 c, Vec2 d){
    return dointersecth(a,b,c,d) && dointersecth(c,d,a,b);
}

void testcase(){
    ll N, M; cin >> N >> M;
    vector<Vec2> A(N+1);
    vector<ll> I(N+1);
    rep(i,N) cin >> A[i].x >> A[i].y;
    A[N] = A[0];
    rep(i,M){
        Vec2 a; cin >> a.x >> a.y;
        bool done = false;
        rep(j,A.size()) if(A[j] == a){
            I[j] = 1;
            done = true;
        }
        if(!done)rep(j,A.size()-1){
            if(
                (A[j+1] - A[j]).dot(a - A[j]) >= 0 &&
                (A[j] - A[j+1]).dot(a - A[j+1]) >= 0 &&
                (A[j+1] - A[j]).cross(a - A[j]) == 0
            ){
                A.insert(A.begin() + j + 1, a);
                I.insert(I.begin() + j + 1, 1);
                done = true;
                break;
            }
        }
    }
    //for(auto [u,v] : A){ cout << u << "," << v << " "; } cout << endl;
    vector<ll> Idx; rep(i,I.size()) if(I[i]) Idx.push_back(i);
    Idx.push_back(Idx.front());
    N = A.size() - 1;
    vector<vector<double>> dist(N, vector<double>(N,1e100));
    rep(i,N) dist[i][i] = 0;
    rep(a,N) rep(b,N) if(a < b){
        bool ok = true;
        rep(f,N) if(f != a && f != b && (f+1)%N != a && (f+1)%N != b){
            if(dointersect(A[a], A[b], A[f], A[f+1])){ ok = false; break; }
        }
        rep(ff,2){
            ll xa = (a == 0 ? N-1 : a-1);
            ll ya = (a == N-1 ? 0 : a+1);
            if((A[ya] - A[a]).cross(A[xa] - A[a]) > 0){
                if((A[ya] - A[a]).cross(A[b] - A[a]) < 0) ok = false;
                if((A[xa] - A[a]).cross(A[b] - A[a]) > 0) ok = false;
            } else {
                if((A[ya] - A[a]).cross(A[b] - A[a]) < 0 &&
                   (A[xa] - A[a]).cross(A[b] - A[a]) > 0) ok = false;
            }
            swap(a,b);
        }
        //if(ok){ cout << a << " " << b << endl; }
        if(ok){
            double d = sqrt(double((A[b]-A[a]).dot(A[b]-A[a])));
            dist[a][b] = d;
            dist[b][a] = d;
        }
    }
    rep(j,N) rep(i,N) rep(k,N) chmin(dist[i][k], dist[i][j] + dist[j][k]);
    //rep(i,N){
    //    cout.precision(3); cout<<fixed;
    //    rep(j,N){
    //        if(dist[i][j] > 1.0e50){ cout << "----- "; } else cout << dist[i][j] << " ";
    //    } cout << endl;
    //}
    double ans = 0;
    rep(i,Idx.size()-1) ans += dist[Idx[i]%N][Idx[i+1]%N];
    cout.precision(20);
    cout << fixed;
    cout << ans << "\n";
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    #ifdef NACHIA
    ll T; cin >> T; rep(t,T){
    #endif
    testcase();
    
    #ifdef NACHIA
    cout << "---------------------" << endl; }
    #endif
    return 0;
}
accuracy: 0.0625
time_ms: 10
memory_kb: 3468
final_rank: 7

code_snippet: #ifdef NACHIA
#define _GLIBCXX_DEBUG
#endif

#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <queue>
#include <cmath>
using namespace std;
using ll = long long;
template<class A, class B> void chmax(A& a, const B& b){ if(a < b) a = b; }
template<class A, class B> void chmin(A& a, const B& b){ if(b < a) a = b; }
using PLL = pair<ll, ll>;
#define rep(i,n) for(ll i=0; i<ll(n); i++)

const ll INF = 1001001001001001001;

struct Vec2 {
    ll x = 0, y = 0;
    friend Vec2 operator+(Vec2 l, Vec2 r){ return { l.x + r.x, l.y + r.y }; }
    friend Vec2 operator-(Vec2 l, Vec2 r){ return { l.x - r.x, l.y - r.y }; }
    friend bool operator==(Vec2 l, Vec2 r){ return l.x == r.x && l.y == r.y; }
    ll dot(Vec2 r) const { return x * r.x + y * r.y; }
    ll cross(Vec2 r) const { return x * r.y - y * r.x; }
};

bool dointersecth(Vec2 a, Vec2 b, Vec2 c, Vec2 d){
    ll adir = (d-c).cross(a-c);
    ll bdir = (d-c).cross(b-c);
    if(adir > 0 && bdir > 0) return false;
    if(adir < 0 && bdir < 0) return false;
    return true;
}

bool dointersect(Vec2 a, Vec2 b, Vec2 c, Vec2 d){
    return dointersecth(a,b,c,d) && dointersecth(c,d,a,b);
}

void testcase(){
    ll N, M; cin >> N >> M;
    vector<Vec2> A(N+1);
    vector<ll> I(N+1);
    rep(i,N) cin >> A[i].x >> A[i].y;
    A[N] = A[0];
    rep(i,M){
        Vec2 a; cin >> a.x >> a.y;
        bool done = false;
        rep(j,A.size()) if(A[j] == a){
            I[j] = 1;
            done = true;
        }
        if(!done)rep(j,A.size()-1){
            if(
                (A[j+1] - A[j]).dot(a - A[j]) >= 0 &&
                (A[j] - A[j+1]).dot(a - A[j+1]) >= 0 &&
                (A[j+1] - A[j]).cross(a - A[j]) == 0
            ){
                A.insert(A.begin() + j + 1, a);
                I.insert(I.begin() + j + 1, 1);
                done = true;
                break;
            }
        }
    }
    //for(auto [u,v] : A){ cout << u << "," << v << " "; } cout << endl;
    vector<ll> Idx; rep(i,I.size()) if(I[i]) Idx.push_back(i);
    Idx.push_back(Idx.front());
    N = A.size() - 1;
    vector<vector<double>> dist(N, vector<double>(N,1e100));
    rep(i,N) dist[i][i] = 0;
    rep(a,N) rep(b,N) if(a < b){
        bool ok = true;
        rep(f,N) if(f != a && f != b && (f+1)%N != a && (f+1)%N != b){
            if(dointersect(A[a], A[b], A[f], A[f+1])){ ok = false; break; }
        }
        rep(ff,2){
            ll xa = (a == 0 ? N-1 : a-1);
            ll ya = (a == N-1 ? 0 : a+1);
            if((A[ya] - A[a]).cross(A[xa] - A[a]) > 0){
                if((A[ya] - A[a]).cross(A[b] - A[a]) < 0) ok = false;
                if((A[xa] - A[a]).cross(A[b] - A[a]) > 0) ok = false;
            } else {
                if((A[ya] - A[a]).cross(A[b] - A[a]) < 0 &&
                   (A[xa] - A[a]).cross(A[b] - A[a]) > 0) ok = false;
            }
        }
        //if(ok){ cout << a << " " << b << endl; }
        if(ok){
            double d = sqrt(double((A[b]-A[a]).dot(A[b]-A[a])));
            dist[a][b] = d;
            dist[b][a] = d;
        }
    }
    rep(j,N) rep(i,N) rep(k,N) chmin(dist[i][k], dist[i][j] + dist[j][k]);
    //rep(i,N){
    //    cout.precision(3); cout<<fixed;
    //    rep(j,N){
    //        if(dist[i][j] > 1.0e50){ cout << "----- "; } else cout << dist[i][j] << " ";
    //    } cout << endl;
    //}
    double ans = 0;
    rep(i,Idx.size()-1) ans += dist[Idx[i]%N][Idx[i+1]%N];
    cout.precision(20);
    cout << fixed;
    cout << ans << "\n";
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    #ifdef NACHIA
    ll T; cin >> T; rep(t,T){
    #endif
    testcase();
    
    #ifdef NACHIA
    cout << "---------------------" << endl; }
    #endif
    return 0;
}
accuracy: 0.0625
time_ms: 10
memory_kb: 3668
final_rank: 9

code_snippet: #ifdef NACHIA
#define _GLIBCXX_DEBUG
#endif

#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <queue>
#include <cmath>
using namespace std;
using ll = long long;
template<class A, class B> void chmax(A& a, const B& b){ if(a < b) a = b; }
template<class A, class B> void chmin(A& a, const B& b){ if(b < a) a = b; }
using PLL = pair<ll, ll>;
#define rep(i,n) for(ll i=0; i<ll(n); i++)

const ll INF = 1001001001001001001;

struct Vec2 {
    ll x = 0, y = 0;
    friend Vec2 operator+(Vec2 l, Vec2 r){ return { l.x + r.x, l.y + r.y }; }
    friend Vec2 operator-(Vec2 l, Vec2 r){ return { l.x - r.x, l.y - r.y }; }
    friend bool operator==(Vec2 l, Vec2 r){ return l.x == r.x && l.y == r.y; }
    ll dot(Vec2 r) const { return x * r.x + y * r.y; }
    ll cross(Vec2 r) const { return x * r.y - y * r.x; }
};

bool dointersecth(Vec2 a, Vec2 b, Vec2 c, Vec2 d){
    ll adir = (d-c).cross(a-c);
    ll bdir = (d-c).cross(b-c);
    if(adir > 0 && bdir > 0) return false;
    if(adir < 0 && bdir < 0) return false;
    return true;
}

bool dointersect(Vec2 a, Vec2 b, Vec2 c, Vec2 d){
    return dointersecth(a,b,c,d) && dointersecth(c,d,a,b);
}

void testcase(){
    ll N, M; cin >> N >> M;
    vector<Vec2> A(N+1);
    vector<ll> I(N+1);
    rep(i,N) cin >> A[i].x >> A[i].y;
    A[N] = A[0];
    rep(i,M){
        Vec2 a; cin >> a.x >> a.y;
        bool done = false;
        rep(j,A.size()) if(A[j] == a){
            I[j] = 1;
            done = true;
        }
        if(!done)rep(j,A.size()-1){
            if(
                (A[j+1] - A[j]).dot(a - A[j]) >= 0 &&
                (A[j] - A[j+1]).dot(a - A[j+1]) >= 0 &&
                (A[j+1] - A[j]).cross(a - A[j]) == 0
            ){
                A.insert(A.begin() + j + 1, a);
                I.insert(I.begin() + j + 1, 1);
                done = true;
                break;
            }
        }
    }
    //for(auto [u,v] : A){ cout << u << "," << v << " "; } cout << endl;
    vector<ll> Idx; rep(i,I.size()) if(I[i]) Idx.push_back(i);
    Idx.push_back(Idx.front());
    N = A.size() - 1;
    vector<vector<double>> dist(N, vector<double>(N,1e100));
    rep(i,N) dist[i][i] = 0;
    rep(a,N) rep(b,N) if(a < b){
        bool ok = true;
        rep(f,N) if(f != a && f != b && (f+1)%N != a && (f+1)%N != b){
            if(dointersect(A[a], A[b], A[f], A[f+1])){ ok = false; break; }
        }
        //if(ok){ cout << a << " " << b << endl; }
        if(ok){
            double d = sqrt(double((A[b]-A[a]).dot(A[b]-A[a])));
            dist[a][b] = d;
            dist[b][a] = d;
        }
    }
    rep(j,N) rep(i,N) rep(k,N) chmin(dist[i][k], dist[i][j] + dist[j][k]);
    //rep(i,N){
    //    cout.precision(3); cout<<fixed;
    //    rep(j,N){
    //        if(dist[i][j] > 1.0e50){ cout << "----- "; } else cout << dist[i][j] << " ";
    //    } cout << endl;
    //}
    double ans = 0;
    rep(i,Idx.size()-1) ans += dist[Idx[i]%N][Idx[i+1]%N];
    cout.precision(20);
    cout << fixed;
    cout << ans << "\n";
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    #ifdef NACHIA
    ll T; cin >> T; rep(t,T){
    #endif
    testcase();
    
    #ifdef NACHIA
    cout << "---------------------" << endl; }
    #endif
    return 0;
}
accuracy: 0.0625
time_ms: 10
memory_kb: 3548
final_rank: 8

code_snippet: #line 1 "library/Template/template.hpp"
#include <bits/stdc++.h>
using namespace std;

#define rep(i,a,b) for(int i=(int)(a);i<(int)(b);i++)
#define ALL(v) (v).begin(),(v).end()
#define UNIQUE(v) sort(ALL(v)),(v).erase(unique(ALL(v)),(v).end())
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v,x) lower_bound(ALL(v),(x))-(v).begin()
#define UB(v,x) upper_bound(ALL(v),(x))-(v).begin()

using ll=long long int;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template<typename T>inline bool chmax(T& a,T b){if(a<b){a=b;return 1;}return 0;}
template<typename T>inline bool chmin(T& a,T b){if(a>b){a=b;return 1;}return 0;}
template<typename T,typename U>T ceil(T x,U y){assert(y!=0); if(y<0)x=-x,y=-y; return (x>0?(x+y-1)/y:x/y);}
template<typename T,typename U>T floor(T x,U y){assert(y!=0); if(y<0)x=-x,y=-y; return (x>0?x/y:(x-y+1)/y);}
template<typename T>int popcnt(T x){return __builtin_popcountll(x);}
template<typename T>int topbit(T x){return (x==0?-1:63-__builtin_clzll(x));}
template<typename T>int lowbit(T x){return (x==0?-1:__builtin_ctzll(x));}
#line 2 "library/Utility/fastio.hpp"
#include <unistd.h>

class FastIO{
    static constexpr int L=1<<16;
    char rdbuf[L];
    int rdLeft=0,rdRight=0;
    inline void reload(){
        int len=rdRight-rdLeft;
        memmove(rdbuf,rdbuf+rdLeft,len);
        rdLeft=0,rdRight=len;
        rdRight+=fread(rdbuf+len,1,L-len,stdin);
    }
    inline bool skip(){
        for(;;){
            while(rdLeft!=rdRight and rdbuf[rdLeft]<=' ')rdLeft++;
            if(rdLeft==rdRight){
                reload();
                if(rdLeft==rdRight)return false;
            }
            else break;
        }
        return true;
    }
    template<typename T,enable_if_t<is_integral<T>::value,int> =0>inline bool _read(T& x){
        if(!skip())return false;
        if(rdLeft+20>=rdRight)reload();
        bool neg=false;
        if(rdbuf[rdLeft]=='-'){
            neg=true;
            rdLeft++;
        }
        x=0;
        while(rdbuf[rdLeft]>='0' and rdLeft<rdRight){
            x=x*10+(neg?-(rdbuf[rdLeft++]^48):(rdbuf[rdLeft++]^48));
        }
        return true;
    }
    inline bool _read(__int128_t& x){
        if(!skip())return false;
        if(rdLeft+40>=rdRight)reload();
        bool neg=false;
        if(rdbuf[rdLeft]=='-'){
            neg=true;
            rdLeft++;
        }
        x=0;
        while(rdbuf[rdLeft]>='0' and rdLeft<rdRight){
            x=x*10+(neg?-(rdbuf[rdLeft++]^48):(rdbuf[rdLeft++]^48));
        }
        return true;
    }
    inline bool _read(__uint128_t& x){
        if(!skip())return false;
        if(rdLeft+40>=rdRight)reload();
        x=0;
        while(rdbuf[rdLeft]>='0' and rdLeft<rdRight){
            x=x*10+(rdbuf[rdLeft++]^48);
        }
        return true;
    }
    template<typename T,enable_if_t<is_floating_point<T>::value,int> =0>inline bool _read(T& x){
        if(!skip())return false;
        if(rdLeft+20>=rdRight)reload();
        bool neg=false;
        if(rdbuf[rdLeft]=='-'){
            neg=true;
            rdLeft++;
        }
        x=0;
        while(rdbuf[rdLeft]>='0' and rdbuf[rdLeft]<='9' and rdLeft<rdRight){
            x=x*10+(rdbuf[rdLeft++]^48);
        }
        if(rdbuf[rdLeft]!='.')return true;
        rdLeft++;
        T base=.1;
        while(rdbuf[rdLeft]>='0' and rdbuf[rdLeft]<='9' and rdLeft<rdRight){
            x+=base*(rdbuf[rdLeft++]^48);
            base*=.1;
        }
        if(neg)x=-x;
        return true;
    }
    inline bool _read(char& x){
        if(!skip())return false;
        if(rdLeft+1>=rdRight)reload();
        x=rdbuf[rdLeft++];
        return true;
    }
    inline bool _read(string& x){
        if(!skip())return false;
        for(;;){
            int pos=rdLeft;
            while(pos<rdRight and rdbuf[pos]>' ')pos++;
            x.append(rdbuf+rdLeft,pos-rdLeft);
            if(rdLeft==pos)break;
            rdLeft=pos;
            if(rdLeft==rdRight)reload();
            else break;
        }
        return true;
    }
    template<typename T>inline bool _read(vector<T>& v){
        for(auto& x:v){
            if(!_read(x))return false;
        }
        return true;
    }

    char wtbuf[L],tmp[50];
    int wtRight=0;
    inline void flush(){
        fwrite(wtbuf,1,wtRight,stdout);
        wtRight=0;
    }
    inline void _write(const char& x){
        if(wtRight>L-32)flush();
        wtbuf[wtRight++]=x;
    }
    inline void _write(const string& x){
        for(auto& c:x)_write(c);
    }
    template<typename T,enable_if_t<is_integral<T>::value,int> =0>inline void _write(T x){
        if(wtRight>L-32)flush();
        if(x==0){
            _write('0');
            return;
        }
        else if(x<0){
            _write('-');
            if (__builtin_expect(x == std::numeric_limits<T>::min(), 0)) {
                switch (sizeof(x)) {
                case 2: _write("32768"); return;
                case 4: _write("2147483648"); return;
                case 8: _write("9223372036854775808"); return;
                }
            }
            x=-x;
        }
        int pos=0;
        while(x!=0){
            tmp[pos++]=char((x%10)|48);
            x/=10;
        }
        rep(i,0,pos)wtbuf[wtRight+i]=tmp[pos-1-i];
        wtRight+=pos;
    }
    inline void _write(__int128_t x){
        if(wtRight>L-40)flush();
        if(x==0){
            _write('0');
            return;
        }
        else if(x<0){
            _write('-');
            x=-x;
        }
        int pos=0;
        while(x!=0){
            tmp[pos++]=char((x%10)|48);
            x/=10;
        }
        rep(i,0,pos)wtbuf[wtRight+i]=tmp[pos-1-i];
        wtRight+=pos;
    }
    inline void _write(__uint128_t x){
        if(wtRight>L-40)flush();
        if(x==0){
            _write('0');
            return;
        }
        int pos=0;
        while(x!=0){
            tmp[pos++]=char((x%10)|48);
            x/=10;
        }
        rep(i,0,pos)wtbuf[wtRight+i]=tmp[pos-1-i];
        wtRight+=pos;
    }
    template<typename T>inline void _write(const vector<T>& v){
        rep(i,0,v.size()){
            if(i)_write(' ');
            _write(v[i]);
        }
    }
public:
    FastIO(){}
    ~FastIO(){flush();}
    inline void read(){}
    template <typename Head, typename... Tail>inline void read(Head& head,Tail&... tail){
        assert(_read(head));
        read(tail...); 
    }
    template<bool ln=true,bool space=false>inline void write(){if(ln)_write('\n');}
    template <bool ln=true,bool space=false,typename Head, typename... Tail>inline void write(const Head& head,const Tail&... tail){
        if(space)_write(' ');
        _write(head);
        write<ln,true>(tail...); 
    }
};

/**
 * @brief Fast IO
 */
#line 3 "sol.cpp"

#line 2 "library/Geometry/geometry.hpp"

using T=double;
const T eps=1e-12;
using Point=complex<T>;
using Poly=vector<Point>;
#define X real()
#define Y imag()
inline bool eq(const T& a,const T& b){
    return fabs(a-b)<eps;
}
bool cmp(const Point& a,const Point& b){
    auto sub=[&](Point a){return (a.Y<0?-1:(a.Y==0&&a.X>=0?0:1));};
    if(sub(a)!=sub(b))return sub(a)<sub(b);
    return a.Y*b.X<a.X*b.Y;
}
struct Line{
    Point a,b;
    Line(){}
    Line(Point _a,Point _b):a(_a),b(_b){}
    Line(T A,T B,T C){
        if(eq(A,.0)){
            a=Point(0,C/B),b=Point(1/C/B);
        }
        else if(eq(B,.0)){
            a=Point(C/A,0),b=Point(C/A,1);
        }
        else{
            a=Point(0,C/B),b=Point(C/A,0);
        }
    }
};
struct Segment:Line{
    Segment(){}
    Segment(Point _a,Point _b):Line(_a,_b){}
};
struct Circle{
    Point p; T r;
    Circle(){}
    Circle(Point _p,T _r):p(_p),r(_r){}
};

istream& operator>>(istream& is,Point& p){
    T x,y; is>>x>>y; p=Point(x,y);
    return is;
}
ostream& operator<<(ostream& os,Point& p){
    os<<fixed<<setprecision(12)<<p.X<<' '<<p.Y;
    return os;
}
Point unit(const Point& a){return a/abs(a);}
T dot(const Point& a,const Point& b){
    return a.X*b.X+a.Y*b.Y;
}
T cross(const Point& a,const Point& b){
    return a.X*b.Y-a.Y*b.X;
}
Point rot(const Point& a,const T& theta){
    return Point(cos(theta)*a.X-sin(theta)*a.Y,
        sin(theta)*a.X+cos(theta)*a.Y);
}
T arg(const Point& a,const Point& b,const Point& c){
    return acos(dot(a-b,c-b)/abs(a-b)/abs(c-b));
}

Point Projection(const Line&l,const Point& p){
    T t=dot(p-l.a,l.a-l.b)/norm(l.a-l.b);
    return l.a+(l.a-l.b)*t;
}
Point Projection(const Segment&l,const Point& p){
    T t=dot(p-l.a,l.a-l.b)/norm(l.a-l.b);
    return l.a+(l.a-l.b)*t;
}
Point Reflection(const Line& l,const Point& p){
    return p+(Projection(l,p)-p)*2.;
}
int ccw(const Point& a,Point b,Point c){
    b-=a; c-=a;
    if(cross(b,c)>eps)return 1; //ccw
    if(cross(b,c)<-eps)return -1; //cw
    if(dot(b,c)<0)return 2; //c,a,b
    if(norm(b)<norm(c))return -2; //a,b,c
    return 0; //a,c,b
}
bool isOrthogonal(const Line& a,const Line& b){
    return eq(dot(a.b-a.a,b.b-b.a),.0);
}
bool isParallel(const Line& a,const Line& b){
    return eq(cross(a.b-a.a,b.b-b.a),.0);
}
bool isIntersect(const Segment& a,const Segment& b){
    return ccw(a.a,a.b,b.a)*ccw(a.a,a.b,b.b)<=0 and
        ccw(b.a,b.b,a.a)*ccw(b.a,b.b,a.b)<=0;
}
int isIntersect(const Circle& a,const Circle& b){
    T d=abs(a.p-b.p);
    if(d>a.r+b.r+eps)return 4;
    if(eq(d,a.r+b.r))return 3;
    if(eq(d,abs(a.r-b.r)))return 1;
    if(d<abs(a.r-b.r)-eps)return 0;
    return 2;
}
T Dist(const Line& a,const Point& b){
    Point c=Projection(a,b);
    return abs(c-b);
}
T Dist(const Segment& a,const Point& b){
    if(dot(a.b-a.a,b-a.a)<eps)return abs(b-a.a);
    if(dot(a.a-a.b,b-a.b)<eps)return abs(b-a.b);
    return abs(cross(a.b-a.a,b-a.a))/abs(a.b-a.a);
}
T Dist(const Segment& a,const Segment& b){
    if(isIntersect(a,b))return .0;
    T res=min({Dist(a,b.a),Dist(a,b.b),Dist(b,a.a),Dist(b,a.b)});
    return res;
}
Point Intersection(const Line& a,const Line& b){
    T d1=cross(a.b-a.a,b.b-b.a);
    T d2=cross(a.b-a.a,a.b-b.a);
    if(eq(d1,0) and eq(d2,0))return b.a;
    return b.a+(b.b-b.a)*(d2/d1);
}
Poly Intersection(const Circle& a,const Line& b){
    Poly res;
    T d=Dist(b,a.p);
    if(d>a.r+eps)return res;
    Point h=Projection(b,a.p);
    if(eq(d,a.r)){
        res.push_back(h);
        return res;
    }
    Point e=unit(b.b-b.a);
    T ph=sqrt(a.r*a.r-d*d);
    res.push_back(h-e*ph);
    res.push_back(h+e*ph);
    return res;
}
Poly Intersection(const Circle& a,const Segment& b){
    Line c(b.a,b.b);
    Poly sub=Intersection(a,c);
    double xmi=min(b.a.X,b.b.X),xma=max(b.a.X,b.b.X);
    double ymi=min(b.a.Y,b.b.Y),yma=max(b.a.Y,b.b.Y);
    Poly res;
    rep(i,0,sub.size()){
        if(xmi<=sub[i].X+eps and sub[i].X-eps<=xma and
            ymi<=sub[i].Y+eps and sub[i].Y-eps<=yma){
            res.push_back(sub[i]);
        }
    }
    return res;
}
Poly Intersection(const Circle& a,const Circle& b){
    Poly res;
    int mode=isIntersect(a,b);
    T d=abs(a.p-b.p);
    if(mode==4 or mode==0)return res;
    if(mode==3){
        T t=a.r/(a.r+b.r);
        res.push_back(a.p+(b.p-a.p)*t);
        return res;
    }
    if(mode==1){
        if(b.r<a.r-eps){
            res.push_back(a.p+(b.p-a.p)*(a.r/d));
        }
        else{
            res.push_back(b.p+(a.p-b.p)*(b.r/d));
        }
        return res;
    }
    T rc=(a.r*a.r+d*d-b.r*b.r)/d/2.;
    T rs=sqrt(a.r*a.r-rc*rc);
    if(a.r-abs(rc)<eps)rs=0;
    Point e=unit(b.p-a.p);
    res.push_back(a.p+rc*e+rs*e*Point(0,1));
    res.push_back(a.p+rc*e+rs*e*Point(0,-1));
    return res;
}
T Area(const Poly& a){
    T res=0;
    int n=a.size();
    rep(i,0,n)res+=cross(a[i],a[(i+1)%n]);
    return fabs(res/2.);
}
T Area(const Poly& a,const Circle& b){
    int n=a.size();
    if(n<3)return .0;
    auto rec=[&](auto self,const Circle& c,const Point& p1,const Point& p2){
        Point va=c.p-p1,vb=c.p-p2;
        T f=cross(va,vb),res=.0;
        if(eq(f,.0))return res;
        if(max(abs(va),abs(vb))<c.r+eps)return f;
        if(Dist(Segment(p1,p2),c.p)>c.r-eps)return c.r*c.r*arg(vb*conj(va));
        auto u=Intersection(c,Segment(p1,p2));
        Poly sub;
        sub.push_back(p1);
        for(auto& x:u)sub.push_back(x);
        sub.push_back(p2);
        rep(i,0,sub.size()-1)res+=self(self,c,sub[i],sub[i+1]);
        return res;
    };
    T res=.0;
    rep(i,0,n)res+=rec(rec,b,a[i],a[(i+1)%n]);
    return fabs(res/2.);
}
T Area(const Circle& a,const Circle& b){
    T d=abs(a.p-b.p);
    if(d>=a.r+b.r-eps)return .0;
    if(d<=abs(a.r-b.r)+eps){
        T r=min(a.r,b.r);
        return M_PI*r*r;
    }
    T ath=acos((a.r*a.r+d*d-b.r*b.r)/d/a.r/2.);
    T res=a.r*a.r*(ath-sin(ath*2)/2.);
    T bth=acos((b.r*b.r+d*d-a.r*a.r)/d/b.r/2.);
    res+=b.r*b.r*(bth-sin(bth*2)/2.);
    return fabs(res);
}
bool isConvex(const Poly& a){
    int n=a.size();
    int cur,pre,nxt;
    rep(i,0,n){
        pre=(i-1+n)%n;
        nxt=(i+1)%n;
        cur=i;
        if(ccw(a[pre],a[cur],a[nxt])==-1)return 0;
    }
    return 1;
}
int isContained(const Poly& a,const Point& b){ // 0:not contain,1:on edge,2:contain
    bool res=0;
    int n=a.size();
    rep(i,0,n){
        Point p=a[i]-b,q=a[(i+1)%n]-b;
        if(p.Y>q.Y)swap(p,q);
        if(p.Y<eps and eps<q.Y and cross(p,q)>eps)res^=1;
        if(eq(cross(p,q),.0) and dot(p,q)<eps)return 1;
    }
    return (res?2:0);
}
Poly ConvexHull(Poly& a){
    int n=a.size(),k=0;
    sort(ALL(a),[](const Point& p,const Point& q){
        return (eq(p.Y,q.Y)?p.X<q.X:p.Y<q.Y);
    });
    Poly res(n*2);
    for(int i=0;i<n;res[k++]=a[i++]){
        while(k>=2 and cross(res[k-1]-res[k-2],a[i]-res[k-1])<-eps)k--;
    }
    for(int i=n-2,t=k+1;i>=0;res[k++]=a[i--]){
        while(k>=t and cross(res[k-1]-res[k-2],a[i]-res[k-1])<-eps)k--;
    }
    res.resize(k-1); return res;
}
T Diam(const Poly& a){
    int n=a.size();
    int x=0,y=0;
    rep(i,1,n){
        if(a[i].Y>a[x].Y)x=i;
        if(a[i].Y<a[y].Y)y=i;
    }
    T res=abs(a[x]-a[y]);
    int i=x,j=y;
    do{
        if(cross(a[(i+1)%n]-a[i],a[(j+1)%n]-a[j])<0)i=(i+1)%n;
        else j=(j+1)%n;
        chmax(res,abs(a[i]-a[j]));
    }while(i!=x or j!=y);
    return res;
}
Poly Cut(const Poly& a,const Line& l){
    int n=a.size(); Poly res;
    rep(i,0,n){
        Point p=a[i],q=a[(i+1)%n];
        if(ccw(l.a,l.b,p)!=-1)res.push_back(p);
        if(ccw(l.a,l.b,p)*ccw(l.a,l.b,q)<0)res.push_back(Intersection(Line(p,q),l));
    }
    return res;
}

T Closest(Poly& a){
    int n=a.size();
    if(n<=1)return 0;
    sort(ALL(a),[&](Point a,Point b){return (eq(a.X,b.X)?a.Y<b.Y:a.X<b.X);});
    Poly buf(n);
    auto rec=[&](auto self,int lb,int rb)->T{
        if(rb-lb<=1)return (T)INF;
        int mid=(lb+rb)>>1;
        auto x=a[mid].X;
        T res=min(self(self,lb,mid),self(self,mid,rb));
        inplace_merge(a.begin()+lb,a.begin()+mid,a.begin()+rb,
            [&](auto p,auto q){return p.Y<q.Y;});
        int ptr=0;
        rep(i,lb,rb){
            if(abs(a[i].X-x)>=res)continue;
            rep(j,0,ptr){
            auto sub=a[i]-buf[ptr-1-j];
            if(sub.Y>=res)break;
            chmin(res,abs(sub));
            }
            buf[ptr++]=a[i];
        }
        return res;
    };
    return rec(rec,0,n);
}

Circle Incircle(const Point& a,const Point& b,const Point& c){
    T A=abs(b-c),B=abs(c-a),C=abs(a-b);
    Point p(A*a.X+B*b.X+C*c.X,A*a.Y+B*b.Y+C*c.Y);
    p/=(A+B+C);
    T r=Dist(Line(a,b),p);
    return Circle(p,r);
}
Circle Circumcircle(const Point& a,const Point& b,const Point& c){
    Line l1((a+b)/2.,(a+b)/2.+(b-a)*Point(0,1));
    Line l2((b+c)/2.,(b+c)/2.+(c-b)*Point(0,1));
    Point p=Intersection(l1,l2);
    return Circle(p,abs(p-a));
}
Poly tangent(const Point& a,const Circle& b){
    return Intersection(b,Circle(a,sqrt(norm(b.p-a)-b.r*b.r)));
}
vector<Line> tangent(const Circle& a,const Circle& b){
    vector<Line> res;
    T d=abs(a.p-b.p);
    if(eq(d,0))return res;
    Point u=unit(b.p-a.p);
    Point v=u*Point(0,1);
    for(int t:{-1,1}){
        T h=(a.r+b.r*t)/d;
        if(eq(h*h,1)){
            res.push_back(Line(a.p+(h>0?u:-u)*a.r,
            a.p+(h>0?u:-u)*a.r+v));
        }
        else if(1>h*h){
            Point U=u*h,V=v*sqrt(1-h*h);
            res.push_back(Line(a.p+(U+V)*a.r,b.p-(U+V)*(b.r*t)));
            res.push_back(Line(a.p+(U-V)*a.r,b.p-(U-V)*(b.r*t)));
        }
    }
    return res;
}

/**
 * @brief Geometry
 */
#line 5 "sol.cpp"

FastIO io;
int main(){
    int n,m;
    io.read(n,m);
    Poly a(n),b(m);
    rep(i,0,n){
        int x,y;
        io.read(x,y);
        a[i]=Point(x,y);
    }
    rep(i,0,m){
        int x,y;
        io.read(x,y);
        b[i]=Point(x,y);
    }

    auto aa=a;
    aa.push_back(a.front());
    aa.push_back(a.front());

    vector<pair<int,T>> lex(m);
    rep(i,0,m){
        rep(hen,0,n){
            if(ccw(b[i],aa[hen],aa[hen+1])==2 or norm(b[i]-aa[hen])<eps){
                lex[i]={hen,norm(b[i]-aa[hen])};
                break;
            }
        }
    }
    vector<int> ord(m);
    iota(ALL(ord),0);
    sort(ALL(ord),[&](int i,int j){return lex[i]<lex[j];});
    ord.push_back(ord.front());

    Poly c=a;
    c.insert(c.end(),ALL(b));

    vector dist(n+m,vector<T>(n+m,inf));
    rep(i,0,n+m)rep(j,0,n+m){
        bool ok=1;
        Segment l1(c[i],c[j]);
        rep(hen,0,n){
            Segment l2(aa[hen],aa[hen+1]);
            if(isIntersect(l1,l2)){
                if(isParallel(l1,l2))continue;
                Point p=Intersection(l1,l2);
                if(p!=c[i] and p!=c[j] and p!=aa[hen] and p!=aa[hen+1]){
                    ok=0;
                    break;
                }
            }
        }
        if(!isContained(a,(c[i]+c[j])*.5))ok=0;
        if(ok)dist[i][j]=sqrt(norm(c[i]-c[j]));
    }

    rep(k,0,n+m)rep(i,0,n+m)rep(j,0,n+m)chmin(dist[i][j],dist[i][k]+dist[k][j]);

    T ret=0;
    rep(i,0,m)ret+=dist[n+ord[i]][n+ord[i+1]];
    printf("%.12f\n",ret);
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3948
final_rank: 4

code_snippet: /*
--------------              |   /
      |                     |  /
      |                     | /
      |             *       |/          |    |         ------            *
      |                     |           |    |        /      \
      |             |       |\          |    |       |       |\          |
   \  |             |       | \         |    |       |       | \         |
    \ |             |       |  \        |    |        \     /   \        |
     V              |       |   \        \__/|         -----     \       |
*/
#include <bits/stdc++.h>
using namespace std;

#ifdef EMT
#define debug(x) cerr << "\e[1;31m" << #x << " = " << (x) << "\e[0m\n"
#define print(x) emilia_mata_tenshi(#x, begin(x), end(x))
template<typename T, typename T2> ostream& operator<<(ostream &os, const pair<T, T2> &obj) {
    return os << '{' << obj.first << ',' << obj.second << '}';
}
template<class TupType, size_t... I> void lamy_kawaii(ostream& os, const TupType& _tup, index_sequence<I...>) {
    // source: https://stackoverflow.com/a/41171552
    os << '{';
    (..., (cerr << (I == 0? "" : ",") << get<I>(_tup)));
    os << '}';
}
template<class... T> ostream& operator<<(ostream &os, const tuple<T...>& _tup) {
    lamy_kawaii(os, _tup, make_index_sequence<sizeof...(T)>());
    return os;
}
template<typename T> void emilia_mata_tenshi(const char *s, T l, T r) {
    cerr << "\e[1;33m" << s << " = [";
    while (l != r) {
        cerr << *l;
        cerr << (++l == r ? ']' : ',');
    }
    cerr << "\e[0m\n";
}
#else
#define debug(x) 48763
#define print(x) 48763
#endif

template<typename T, typename T2> istream& operator>>(istream &is, pair<T, T2> &obj) {
    is >> obj.first >> obj.second;
    return is;
}
template<typename T> istream& operator>>(istream &is, vector<T> &obj) {
    for (auto &x : obj)
        is >> x;
    return is;
}

#define YN(x) ((x) ? "YES" : "NO")
#define Yn(x) ((x) ? "Yes" : "No")
#define yn(x) ((x) ? "yes" : "no")
#define emilia_my_wife ios::sync_with_stdio(0); cin.tie(NULL);
using ll = int64_t;
using ull = uint64_t;
using ld = long double;
using uint = uint32_t;
const double EPS  = 1e-8;
const int INF     = 0x3F3F3F3F;
const ll LINF     = 4611686018427387903;
const int MOD     = 1e9+7;
static int Lamy_is_cute = []() {
    emilia_my_wife
    return 48763;
}();
/*--------------------------------------------------------------------------------------*/

struct point {
    ll x, y;
    point() { }
    point(ll a, ll b): x(a), y(b) { }
    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*(ld r) const {
        return point(x * r, y * r);
    }
    point operator/(ld r) const {
        return point(x / r, y / r);
    }
    bool operator<(const point &b) const {
        return x == b.x ? x < b.x : y < b.y; }
    ld dis2() { return x * x + y * y; }
    ld dis() { return sqrtl(dis2()); }
    point perp() { return point(-y, x); }
    point norm() {
        ld d = dis();
        return point(x / d, y / d);
    }
};
ll cross(const point &a, const point &b, const point &c) {
    auto x = b - a, y = c - a;
    return x.x * y.y - y.x * x.y;
}
ll dot(const point &a, const point &b, const point &c) {
    auto x = b - a, y = c - a;
    return x.x * y.x + x.y * y.y;
}
ll area(const point &a, const point &b, const point &c) {
    return ll(cross(a, b, c)) / 2;
}
static inline bool eq(ld a, ld b) { return abs(a - b) < EPS; }
int sgn(ll v) {
    return v > 0 ? 1 : (v < 0 ? -1 : 0);
}
int ori(point a, point b, point c) {
    return sgn(cross(a, b, c));
}
bool collinearity(point a, point b, point c) {
    return ori(a, b, c) == 0;
}
bool btw(point p, point a, point b) { // strict
    // cerr << "> " <<p.x << ' ' << p.y << ' ' << a.x << ' ' << a.y << ' ' << b.x << ' ' << b.y << ' ' << sgn(dot(p, a, b)) << '\n';
    return collinearity(p, a, b) && sgn(dot(p, a, b)) < 0;
}
bool btw2(point p, point a, point b) {
    return collinearity(p, a, b) && sgn(dot(p, a, b)) <= 0;
}
point projection(point p1, point p2, point p3) {
    return (p2 - p1) * dot(p1, p2, p3) / (p2 - p1).dis2();
}
using Line = pair<point, point>;
bool seg_intersect(Line a, Line b) {
    point p1, p2, p3, p4;
    tie(p1, p2) = a;
    tie(p3, p4) = b;
    // if (btw(p1, p3, p4) || btw(p2, p3, p4) || btw(p3, p1, p2) || btw(p4, p1, p2))
    //     return true;
    return ori(p1, p2, p3) * ori(p1, p2, p4) < 0 &&
        ori(p3, p4, p1) * ori(p3, p4, p2) < 0;
}
point intersect(Line a, Line b) {
    point p1, p2, p3, p4;
    tie(p1, p2) = a;
    tie(p3, p4) = b;
    ld a123 = cross(p1, p2, p3);
    ld a124 = cross(p1, p2, p4);
    return (p4 * a123 - p3 * a124) / (a123 - a124);
}

const int N = 207;
ld dis[N][N], ans[N][N];

signed main() {
    int n, m;
    cin >> n >> m;
    vector<point> arr(n + m);
    for (auto &[a, b] : arr)
        cin >> a >> b;
    for (int i = 0; i < n + m; i++)
        for (int j = 0; j < n + m; j++)
            dis[i][j] = ans[i][j] = 1e18;
    auto test = [&](int a, int b) {
        if (arr[a].x == arr[b].x && arr[a].y == arr[b].y)
            return true;
        int id = -1;
        for (int i = 0; i < n; i++) {
            if (btw(arr[i], arr[a], arr[b]))
                return false;
            if (seg_intersect({arr[i], arr[(i + 1) % n]}, {arr[a], arr[b]}))
                return false;
            if (arr[i].x == arr[a].x && arr[i].y == arr[a].y)
                id = i;
        }
        // debug(make_tuple(a, b, id));
        if (~id) {
            int i = id;
            if (ori(arr[(id + n - 1) % n], arr[id], arr[(i + 1) % n]) > 0)
                return ori(arr[i], arr[(i + n - 1) % n], arr[b]) <= 0 && ori(arr[i], arr[b], arr[(i + 1) % n]) <= 0;
            else
                return !(ori(arr[i], arr[(i + n - 1) % n], arr[b]) > 0 && ori(arr[i], arr[b], arr[(i + 1) % n]) > 0);
        }
        else {
            for (int i = 0; i < n; i++) {
                if (btw(arr[a], arr[i], arr[(i + 1) % n])) {
                    return ori(arr[i], arr[(i + 1) % n], arr[b]) >= 0;
                }
            }
            return false;
        }
    };
    for (int i = 0; i < n + m; i++) {
        for (int j = 0; j < n + m; j++) {
            bool ok = test(i, j);
            // cerr << "> " << i << ' ' << j << ' ' << ok << '\n';
            if (ok) {
                dis[i][j] = (arr[j] - arr[i]).dis();
            }
        }
    }

    vector<pair<int, int>> ord;
    for (int i = n; i < n + m; i++) {
        for (int j = 0; j < n; j++) {
            if (btw2(arr[i], arr[j], arr[(j + 1) % n])) {
                ord.push_back({j, i});
                break;
            }
        }
    }
    sort(ord.begin(), ord.end(), [&](auto a, auto b) {
        return a.first == b.first ? (arr[a.second] - arr[a.first]).dis2() < (arr[b.second] - arr[b.first]).dis2() : a.first < b.first;
    });

    for (int i = n; i < n + m; i++) {
        priority_queue<pair<ld, int>, vector<pair<ld, int>>, greater<pair<ld, int>>> pq;
        ans[i][i] = 0;
        pq.push({ld(0), i});
        while (!pq.empty()) {
            auto [d, u] = pq.top();
            pq.pop();
            if (d > ans[i][u])
                continue;
            for (int v = 0; v < n + m; v++)
                if (ans[i][v] > ans[i][u] + dis[u][v]) {
                    ans[i][v] = ans[i][u] + dis[u][v];
                    pq.push({ans[i][v], v});
                }
        }
    }


    ld tot = 0;
    for (int i = 0; i < m; i++) {
        tot += ans[ord[i].second][ord[(i + 1) % m].second];
    }

    cout << fixed << setprecision(15) << tot << '\n';
}
accuracy: 1
time_ms: 20
memory_kb: 4928
final_rank: 5

code_snippet: /*
--------------              |   /
      |                     |  /
      |                     | /
      |             *       |/          |    |         ------            *
      |                     |           |    |        /      \
      |             |       |\          |    |       |       |\          |
   \  |             |       | \         |    |       |       | \         |
    \ |             |       |  \        |    |        \     /   \        |
     V              |       |   \        \__/|         -----     \       |
*/
#include <bits/stdc++.h>
using namespace std;

#ifdef EMT
#define debug(x) cerr << "\e[1;31m" << #x << " = " << (x) << "\e[0m\n"
#define print(x) emilia_mata_tenshi(#x, begin(x), end(x))
template<typename T, typename T2> ostream& operator<<(ostream &os, const pair<T, T2> &obj) {
    return os << '{' << obj.first << ',' << obj.second << '}';
}
template<class TupType, size_t... I> void lamy_kawaii(ostream& os, const TupType& _tup, index_sequence<I...>) {
    // source: https://stackoverflow.com/a/41171552
    os << '{';
    (..., (cerr << (I == 0? "" : ",") << get<I>(_tup)));
    os << '}';
}
template<class... T> ostream& operator<<(ostream &os, const tuple<T...>& _tup) {
    lamy_kawaii(os, _tup, make_index_sequence<sizeof...(T)>());
    return os;
}
template<typename T> void emilia_mata_tenshi(const char *s, T l, T r) {
    cerr << "\e[1;33m" << s << " = [";
    while (l != r) {
        cerr << *l;
        cerr << (++l == r ? ']' : ',');
    }
    cerr << "\e[0m\n";
}
#else
#define debug(x) 48763
#define print(x) 48763
#endif

template<typename T, typename T2> istream& operator>>(istream &is, pair<T, T2> &obj) {
    is >> obj.first >> obj.second;
    return is;
}
template<typename T> istream& operator>>(istream &is, vector<T> &obj) {
    for (auto &x : obj)
        is >> x;
    return is;
}

#define YN(x) ((x) ? "YES" : "NO")
#define Yn(x) ((x) ? "Yes" : "No")
#define yn(x) ((x) ? "yes" : "no")
#define emilia_my_wife ios::sync_with_stdio(0); cin.tie(NULL);
using ll = int64_t;
using ull = uint64_t;
using ld = long double;
using uint = uint32_t;
const double EPS  = 1e-8;
const int INF     = 0x3F3F3F3F;
const ll LINF     = 4611686018427387903;
const int MOD     = 1e9+7;
static int Lamy_is_cute = []() {
    emilia_my_wife
    return 48763;
}();
/*--------------------------------------------------------------------------------------*/

struct point {
    ll x, y;
    point() { }
    point(ll a, ll b): x(a), y(b) { }
    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*(ld r) const {
        return point(x * r, y * r);
    }
    point operator/(ld r) const {
        return point(x / r, y / r);
    }
    bool operator<(const point &b) const {
        return x == b.x ? x < b.x : y < b.y; }
    ld dis2() { return x * x + y * y; }
    ld dis() { return sqrtl(dis2()); }
    point perp() { return point(-y, x); }
    point norm() {
        ld d = dis();
        return point(x / d, y / d);
    }
};
ll cross(const point &a, const point &b, const point &c) {
    auto x = b - a, y = c - a;
    return x.x * y.y - y.x * x.y;
}
ll dot(const point &a, const point &b, const point &c) {
    auto x = b - a, y = c - a;
    return x.x * y.x + x.y * y.y;
}
ll area(const point &a, const point &b, const point &c) {
    return ll(cross(a, b, c)) / 2;
}
static inline bool eq(ld a, ld b) { return abs(a - b) < EPS; }
int sgn(ll v) {
    return v > 0 ? 1 : (v < 0 ? -1 : 0);
}
int ori(point a, point b, point c) {
    return sgn(cross(a, b, c));
}
bool collinearity(point a, point b, point c) {
    return ori(a, b, c) == 0;
}
bool btw(point p, point a, point b) { // strict
    // cerr << "> " <<p.x << ' ' << p.y << ' ' << a.x << ' ' << a.y << ' ' << b.x << ' ' << b.y << ' ' << sgn(dot(p, a, b)) << '\n';
    return collinearity(p, a, b) && sgn(dot(p, a, b)) < 0;
}
bool btw2(point p, point a, point b) {
    return collinearity(p, a, b) && sgn(dot(p, a, b)) <= 0;
}
point projection(point p1, point p2, point p3) {
    return (p2 - p1) * dot(p1, p2, p3) / (p2 - p1).dis2();
}
using Line = pair<point, point>;
bool seg_intersect(Line a, Line b) {
    point p1, p2, p3, p4;
    tie(p1, p2) = a;
    tie(p3, p4) = b;
    // if (btw(p1, p3, p4) || btw(p2, p3, p4) || btw(p3, p1, p2) || btw(p4, p1, p2))
    //     return true;
    return ori(p1, p2, p3) * ori(p1, p2, p4) < 0 &&
        ori(p3, p4, p1) * ori(p3, p4, p2) < 0;
}
point intersect(Line a, Line b) {
    point p1, p2, p3, p4;
    tie(p1, p2) = a;
    tie(p3, p4) = b;
    ld a123 = cross(p1, p2, p3);
    ld a124 = cross(p1, p2, p4);
    return (p4 * a123 - p3 * a124) / (a123 - a124);
}

const int N = 207;
ld dis[N][N], ans[N][N];

signed main() {
    int n, m;
    cin >> n >> m;
    vector<point> arr(n + m);
    for (auto &[a, b] : arr)
        cin >> a >> b;
    for (int i = 0; i < n + m; i++)
        for (int j = 0; j < n + m; j++)
            dis[i][j] = ans[i][j] = 1e18;
    auto test = [&](int a, int b) {
        if (arr[a].x == arr[b].x && arr[a].y == arr[b].y)
            return true;
        int id = -1;
        for (int i = 0; i < n; i++) {
            if (btw(arr[i], arr[a], arr[b]))
                return false;
            if (seg_intersect({arr[i], arr[(i + 1) % n]}, {arr[a], arr[b]}))
                return false;
            if (arr[i].x == arr[a].x && arr[i].y == arr[a].y)
                id = i;
        }
        // debug(make_tuple(a, b, id));
        if (~id) {
            int i = id;
            if (ori(arr[(id + n - 1) % n], arr[id], arr[(i + 1) % n]) > 0)
                return ori(arr[i], arr[(i + n - 1) % n], arr[b]) <= 0 && ori(arr[i], arr[b], arr[(i + 1) % n]) <= 0;
            else
                return !(ori(arr[i], arr[(i + n - 1) % n], arr[b]) >= 0 && ori(arr[i], arr[b], arr[(i + 1) % n]) >= 0);
        }
        else {
            for (int i = 0; i < n; i++) {
                if (btw(arr[a], arr[i], arr[(i + 1) % n])) {
                    return ori(arr[i], arr[(i + 1) % n], arr[b]) >= 0;
                }
            }
            return false;
        }
    };
    for (int i = 0; i < n + m; i++) {
        for (int j = 0; j < n + m; j++) {
            bool ok = test(i, j);
            // cerr << "> " << i << ' ' << j << ' ' << ok << '\n';
            if (ok) {
                dis[i][j] = (arr[j] - arr[i]).dis();
            }
        }
    }
    for (int i = 0; i < n; i++)
        dis[i][(i + 1) % n] = dis[(i + 1) % n][i] = (arr[(i + 1) % n] - arr[i]).dis();

    vector<pair<int, int>> ord;
    for (int i = n; i < n + m; i++) {
        for (int j = 0; j < n; j++) {
            if (btw2(arr[i], arr[j], arr[(j + 1) % n])) {
                ord.push_back({j, i});
                break;
            }
        }
    }
    sort(ord.begin(), ord.end(), [&](auto a, auto b) {
        return a.first == b.first ? (arr[a.second] - arr[a.first]).dis2() < (arr[b.second] - arr[b.first]).dis2() : a.first < b.first;
    });

    for (int i = n; i < n + m; i++) {
        priority_queue<pair<ld, int>, vector<pair<ld, int>>, greater<pair<ld, int>>> pq;
        ans[i][i] = 0;
        pq.push({ld(0), i});
        while (!pq.empty()) {
            auto [d, u] = pq.top();
            pq.pop();
            if (d > ans[i][u])
                continue;
            for (int v = 0; v < n + m; v++)
                if (ans[i][v] > ans[i][u] + dis[u][v]) {
                    ans[i][v] = ans[i][u] + dis[u][v];
                    pq.push({ans[i][v], v});
                }
        }
    }


    ld tot = 0;
    for (int i = 0; i < m; i++) {
        tot += ans[ord[i].second][ord[(i + 1) % m].second];
    }

    cout << fixed << setprecision(15) << tot << '\n';
}
accuracy: 0.0625
time_ms: 10
memory_kb: 4472
final_rank: 10

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

using ll=long long;
#define int ll

#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,b) rng(i,0,b)
#define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--)

#define tct template<class t>
#define tctu template<class t,class u>

tctu bool chmax(t&a,u b){
	if(a<b){
		a=b;
		return true;
	}else return false;
}
tctu bool chmin(t&a,u b){
	if(a>b){
		a=b;
		return true;
	}else return false;
}

tct using vc=vector<t>;
tct using vvc=vc<vc<t>>;
using vi=vc<int>;

#define eb emplace_back
#define pb push_back
#define bg begin()
#define ed end()
#define all(x) x.bg,x.ed
#define si(x) int(x.size())

using pi=pair<int,int>;
#define a first
#define b second
#define mp make_pair

tct void mkuni(vc<t>&vs){
	sort(all(vs));
	vs.erase(unique(all(vs)),vs.ed);
}

using ld=ll;
const ld eps=0;
int sgn(ld a){return a<-eps?-1:(a>eps?1:0);}
int sgn(ld a,ld b){return sgn(a-b);}
using pt=complex<ld>;
#define x real()
#define y imag()
ld crs(pt a,pt b){return a.x*b.y-a.y*b.x;}
ld crs(pt a,pt b,pt c){return crs(b-a,c-a);}
int ccw(pt a,pt b){return sgn(crs(a,b));}
int ccw(pt a,pt b,pt c){return sgn(crs(a,b,c));}
ld dot(pt a,pt b){return a.x*b.x+a.y*b.y;}

using ln=pair<pt,pt>;
int ccw(ln a,pt b){return ccw(a.a,a.b,b);}
pt dir(ln a){return a.b-a.a;}
pi cllt(ln a,ln b){
	return pi(crs(b.a,b.b,a.a),crs(dir(a),dir(b)));
}

bool cplt(const vc<pt>&ps,ln z){
	int n=si(ps);
	bool ok=true;
	int cnt=0;
	auto add=[&](int num,int den){
		if(den<0){
			num=-num;
			den=-den;
		}
		if(num<=0){
			cnt++;
		}else if(num>=den){
			
		}else{
			ok=false;
		}
	};
	rep(i,n){
		pt p=ps[i],q=ps[(i+1)%n],r=ps[(i+n-1)%n];
		int a=ccw(z,p),b=ccw(z,q);
		if(a*b==-1){
			auto [num,den]=cllt(z,ln(p,q));
			add(num,den);
		}
		if(a==0){
			int c=ccw(z,r);
			if(b!=c&&(b*c<0||ccw(p,q,r)>0))
				add(dot(ps[i]-z.a,dir(z)),norm(dir(z)));
		}
	}
	return ok&&cnt%2==1;
}

pt readpt(){
	ld a,b;cin>>a>>b;
	return pt(a,b);
}

bool cmppt(pt a,pt b){
	return a.x!=b.x?a.x<b.x:a.y<b.y;
}
bool eqpt(pt a,pt b){
	return a.x==b.x&&a.y==b.y;
}

void slv(){
	int n,m;cin>>n>>m;
	vc<pt> ps(n);
	rep(i,n)ps[i]=readpt();
	vc<pt> qs(m);
	rep(i,m)qs[i]=readpt();
	
	vc<pt> vs=ps;
	vs.insert(vs.ed,all(qs));
	sort(all(vs),cmppt);
	vs.erase(unique(all(vs),eqpt),vs.ed);
	
	int s=si(vs);
	using D=long double;
	vvc<D> d(s,vc<D>(s,1e20));
	rep(i,s)d[i][i]=0;
	
	rep(i,s)rep(j,i){
		if(cplt(ps,ln(vs[i],vs[j]))){
			d[i][j]=d[j][i]=sqrtl(norm(vs[i]-vs[j]));
		}
	}
	rep(k,s)rep(i,s)rep(j,s)chmin(d[i][j],d[i][k]+d[k][j]);
	
	vc<tuple<int,int,int>> buf;
	
	rep(i,m){
		int iv=lower_bound(all(vs),qs[i],cmppt)-vs.bg;
		
		bool done=false;
		rep(j,n){
			ln a(ps[j],ps[(j+1)%n]);
			if(ccw(a,qs[i])==0){
				pt z=dir(a);
				int w=dot(qs[i]-a.a,z);
				if(0<=w&&w<norm(z)){
					assert(!done);
					done=true;
					buf.eb(j,w,iv);
				}
			}
		}
		assert(done);
	}
	
	sort(all(buf));
	
	//cerr<<m<<endl;
	D ans=0;
	rep(i,m){
		int p=get<2>(buf[i]);
		int q=get<2>(buf[(i+1)%m]);
		//cerr<<get<0>(buf[i])<<" "<<get<1>(buf[i])<<" "<<get<2>(buf[i])<<" "<<vs[p].x<<" "<<vs[p].y<<endl;
		ans+=d[p][q];
	}
	cout<<ans<<endl;
}

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);
	
	slv();
}
accuracy: 1
time_ms: 20
memory_kb: 3732
final_rank: 3