#include <bits/stdc++.h>

using namespace std;

using i64 = int64_t;

const i64 INF = 1e18 + 7;
const i64 MOD = 1e9 + 7;

struct UnionFind{
    vector<i64> par;
    UnionFind(i64 n) : par(n, -1){}
    i64 Find(i64 x){return par[x] < 0 ? x : Find(par[x]);}
    bool Unite(i64 x, i64 y){
        x = Find(x);
        y = Find(y);
        if(x == y)
            return false;
        if(par[x] > par[y])
            swap(x, y);
        par[x] += par[y];
        par[y] = x;
        return true;
    }
};

double add(double a, double b){
    if(abs(a + b) < 1e-10 * (abs(a) + abs(b)))
        return 0;
    return a + b;
}
struct poi64{
    double x, y;
    poi64(){}
    poi64(double x, double y) : x(x), y(y){}
    poi64 operator-(const poi64& p){
        return poi64(add(x, -p.x), add(y, -p.y));
    }
    double det(const poi64& p){
        return add(x * p.y, -y * p.x);
    }
};
bool cmp_x(const poi64& p, const poi64& q){
    if(p.x != q.x)
        return p.x < q.x;
    return p.y < q.y;
}

vector<poi64> ch(vector<poi64>& ps){
    i64 n = ps.size();
    sort(ps.begin(), ps.end(), cmp_x);
    i64 k = 0;
    vector<poi64> qs(n * 2);
    for(i64 i = 0; i < n; ++i){
        while(k > 1 && (qs[k - 1] - qs[k - 2]).det(ps[i] - qs[k - 1]) < 0)
            k--;
        qs[k++] = ps[i];
    }
    for(i64 i = n - 2, t = k; i >= 0; i--){
        while(k > t && (qs[k - 1] - qs[k - 2]).det(ps[i] - qs[k - 1]) < 0)
            k--;
        qs[k++] = ps[i];
    }
    qs.resize(k - 1);
    return qs;
}

signed main(){
    i64 n, m;
    cin >> n >> m;
    vector<i64> x(n), y(n);
    vector<pair<i64,i64>> v;
    vector<poi64> v_p;
    for(i64 i = 0; i < n; ++i){
        cin >> x[i] >> y[i];
        v_p.emplace_back(x[i], y[i]);
    }
    auto ch_p = ch(v_p);
    vector<i64> ch_v;
    for(i64 i = 0; i < ch_p.size(); ++i){
        for(i64 j = 0; j < n; ++j)
            if(ch_p[i].x == x[j] && ch_p[i].y == y[j]){
                ch_v.emplace_back(j);
                break;
            }
        assert(ch_v.size() == i + 1);
    }

    auto dist_func = [&](i64 i, i64 j){
        double xd = x[i] - x[j];
        double yd = y[i] - y[j];
        return sqrt(xd * xd + yd * yd);
    };
    set<i64> ch_s;
    for(auto& x : ch_v)
        ch_s.emplace(x);


    double ans = 0;
    for(i64 i = 0; i < ch_v.size(); ++i)
        ans += dist_func(ch_v[i], ch_v[(i + 1) % ch_v.size()]);

    UnionFind uf(n + 1);
    for(i64 i = 0; i < n; ++i){
        bool fl = false;
        for(auto& x : ch_v){
            if(i == x){
                fl = true;
                break;
            }
        }
        if(fl)
            uf.Unite(i, n);
    }

    vector<tuple<double,i64,i64>> eds;
    for(i64 i = 0; i < m; ++i){
        i64 s, t;
        cin >> s >> t;
        --s, --t;
        eds.emplace_back(dist_func(s, t), s, t);
    }
    sort(eds.begin(), eds.end());
    for(auto& ed : eds){
        double dist;
        i64 s, t;
        tie(dist, s, t) = ed;
        if(uf.Unite(s, t)){
            ans += dist;
        }
    }
    printf("%.20lf\n", ans);

}

