#include <bits/stdc++.h>

using namespace std;

#define int long long

typedef unsigned long long ull;

const int MOD = 1e9 + 7;
const int dy[] = { 0, 0, 1, -1 };
const int dx[] = { 1, -1, 0, 0 };

template <class T> void chmin(T& a, const T& b) { a = min(a, b); }
template <class T> void chmax(T& a, const T& b) { a = max(a, b); }

const double EPS = 1e-10;

double add(double a, double b) {
  if(abs(a + b) < EPS * (abs(a) + abs(b))) return 0;
  return a + b;
}

struct Point {
  double x, y;
  int num;
  Point() {}
  Point(double x, double y) : x(x), y(y) {
  }
  Point operator + (Point p) {
    return Point(add(x, p.x), add(y, p.y));
  }
  Point operator - (Point p) {
    return Point(add(x, -p.x), add(y, -p.y));
  }
  Point operator * (double d) {
    return Point(x * d, y * d);
  }
  double dot(Point p) {
    return add(x * p.x, y * p.y);
  }
  double det(Point p) {
    return add(x * p.y, -y * p.x);
  }
};

bool cmp_x(const Point& p, const Point& q) {
  if(p.x != q.x) return p.x < q.x;
  return p.y < q.y;
}

vector<Point> convex_hull(Point *ps, int n) {
  sort(ps, ps + n, cmp_x);
  int k = 0;
  vector<Point> qs(2 * n);

  for(int 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(int 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;
}

int par[100];     //親
int Rank[100];    //木の深さ

void init(int n) {
    for(int i = 0; i < n; ++i) {
        par[i] = i;
        Rank[i] = 0;
    }
}

int find(int x) {
    return (par[x] == x) ? x : par[x] = find(par[x]);
}

void unite(int x, int y) {
    x = find(x);
    y = find(y);
    if(x == y) return;

    if(Rank[x] < Rank[y]) par[x] = y;
    else {
        par[y] = x;
        if(Rank[x] == Rank[y]) ++Rank[x];
    }
}

bool same(int x, int y) {
    return find(x) == find(y);
}

struct edge{ int u, v; double cost; };

bool comp(const edge& e1, const edge& e2) {
    return e1.cost < e2.cost;
}

vector<edge> es;
int V, E;
Point p[101];

double kruskal() {
    sort(es.begin(), es.end(), comp);
    init(V);
    double res = 0;
    for(int i = 0; i < E; ++i) {
        edge e = es[i];
        if(!same(e.u, e.v)) {
            unite(e.u, e.v);
            res += e.cost;
        }
    }
    return res;
}

signed main() {
    cin.tie(0);
    ios::sync_with_stdio(false);

    cin >> V >> E;
    for(int i = 0; i < V; ++i) {
        cin >> p[i].x >> p[i].y;
        p[i].num = i;
    }
    for(int i = 0; i < E; ++i) {
        int s, t;
        cin >> s >> t;
        --s; --t;
        double x = (p[s].x - p[t].x) * (p[s].x - p[t].x);
        double y = (p[s].y - p[t].y) * (p[s].y - p[t].y);
        es.push_back(edge{s, t, sqrt(x + y)});
    }
    vector<Point> ps = convex_hull(p, V);
    ps.push_back(ps[0]);
    double ans = 0;
    for(int i = 0; i < ps.size() - 1; ++i) {
        double x = (ps[i].x - ps[i + 1].x) * (ps[i].x - ps[i + 1].x);
        double y = (ps[i].y - ps[i + 1].y) * (ps[i].y - ps[i + 1].y);
        ans += sqrt(x + y);
        es.push_back(edge{ps[i].num, ps[i + 1].num, 0});
    }
    E = (int)es.size();
    ans += kruskal();
    printf("%.4f\n", ans);
    return 0;
}



Measured memory_bytes: 3320