#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
#define rep(i,s,e) for(int (i) = (s);(i) <= (e);(i)++)
#define all(x) x.begin(),x.end()

#include <algorithm>
#include <cmath>
#include <tuple>
#include <vector>
using namespace std;

using ld = long double;

const ld EPS = 1e-8;
inline bool eq(ld a, ld b) { return abs(a - b) < EPS; }
const ld PI = acos(-1);

struct Geometory {
  struct Point {
    ld x, y;
    Point(ld x = 0, ld y = 0) : 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 ld b) const { return Point(x * b, y * b); }
    Point operator/(const ld b) const { return Point(x / b, y / b); }
    bool operator<(const Point& b) const {
      if (x != b.x)
        return x < b.x;
      else
        return y < b.y;
    }
    bool operator==(const Point& b) const { return eq(x, b.x) && eq(y, b.y); }
    ld norm() const { return x * x + y * y; }
    ld abs() const { return sqrt(norm()); }
    ld arg() const { return atan2(x, y); }
    Point rotate(const ld theta) const {
      ld co = cos(theta);
      ld si = sin(theta);
      return Point(co * x - si * y, si * x + y * co);
    }
    Point rotate90() const { return Point(-y, x); }
  };

  ld dot(const Point& a, const Point& b) { return a.x * b.x + a.y * b.y; }
  ld cross(const Point& a, const Point b) { return a.x * b.y - a.y * b.x; }

  struct Line {
    Point from, to;
    Line(Point from = Point(), Point to = Point()) : from(from), to(to) {}
  };

  struct Segment {
    Point from, to;
    Segment(Point from = Point(), Point to = Point()) : from(from), to(to) {}
  };

  bool is_orthogonal(const Line& la, const Line& lb) {
    return eq(0.0, dot(la.from - la.to, lb.from - lb.from));
  }
  bool is_parallel(const Line& la, const Line& lb) {
    return eq(0.0, cross(la.from - la.to, lb.from - lb.from));
  }
  bool is_Point_on(const Line& l, const Point& p) {
    return eq(0.0, cross(l.to - l.from, p - l.from));
  }
  bool is_Point_on(const Segment& s, const Point& p) {
    return (s.from - p).abs() + (p - s.to).abs() < (s.from - s.to).abs() + EPS;
  }
  ld distance(const Line& l, const Point& p) {
    return abs(cross(l.to - l.from, p - l.from)) / (l.to - l.from).abs();
  }
  ld distance(const Segment& s, const Point& p) {
    if (dot(s.to - s.from, p - s.from) < EPS) return (p - s.from).abs();
    if (dot(s.from - s.to, p - s.to) < EPS) return (p - s.to).abs();
    return abs(cross(s.to - s.from, p - s.from)) / (s.to - s.from).abs();
  }
  ld is_intersected(const Segment& a, const Segment& b) {
    return (cross(a.to - a.from, b.from - a.from) *
                cross(a.to - a.from, b.to - a.from) <
            EPS) &&
           (cross(b.to - b.from, a.from - b.from) *
                cross(b.to - b.from, a.to - b.from) <
            EPS);
  }

  ld is_intersected(const Segment& s, const Line& l) {
    // line -> ax + by + c = 0
    ld a = l.to.y - l.from.y;
    ld b = l.from.x - l.to.x;
    ld c = -a * l.from.x - b * l.from.y;
    ld t1 = a * s.from.x + b * s.from.y + c;
    ld t2 = a * s.to.x + b * s.to.y + c;
    return t1 * t2 <= 0;
  }

  Point intersection_point(const Segment& a, const Segment& b) {
    Point bp = b.to - b.from;
    ld d1 = abs(cross(bp, a.from - b.from));
    ld d2 = abs(cross(bp, a.to - b.from));
    ld t = d1 / (d1 + d2);
    return a.from + (a.to - a.from) * t;
  }

  Point intersection_point(const Line& a, const Line& b) {
    Point ap = a.to - a.from;
    Point bp = b.to - b.from;
    return a.from + ap * cross(bp, b.from - a.from) / cross(bp, ap);
  }
  // counterclockwise
  int ccw(const Point& a, const Point& b, const Point& c) {
    Point ba = b - a;
    Point ca = c - a;
    if (cross(ba, ca) > EPS) return 1;   // a - b --/ c
    if (cross(ba, ca) < EPS) return -1;  // a - b --| c
    if (dot(ba, ca) < 0) return 2;       // b - a - c
    if (b.norm() < c.norm()) return -2;  // a - b - c
    return 0;                            // a -- c -- b
  }

  vector<Point> Convex_Hull(vector<Point>& p) {
    int n = p.size();
    int 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;
    }
  }
};
Geometory geo;

#include <vector>
using namespace std;

struct UnionFind {
  vector<int> par_;
  vector<int> rank_;

  void init(int size) {
    par_.resize(size, 0);
    rank_.resize(size, 0);
    for (int i = 0; i < size; i++) {
      par_[i] = i;
      rank_[i] = 0;
    }
  }
  int root(int x) { return par_[x] == x ? x : par_[x] = root(par_[x]); }

  bool unite(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y) return true;

    if (rank_[x] < rank_[y]) {
      par_[x] = y;
    } else {
      par_[y] = x;
      if (rank_[x] == rank_[y]) rank_[x]++;
    }
    return false;
  }
  bool same(int x, int y) { return root(x) == root(y); }
};

int V;
int R;
using Point = Geometory::Point;
int main(){
  cin >> V;
  cin >> R;
  vector<Point> vs;
  map<Point,int> mp;
  vector<int> idx(V);
  rep(i,0,V - 1){
    double x,y;
    cin >> x >> y;
    vs.push_back(Point(x,y));
  }
  vector<Point> gen = vs;
  if(V > 3)
    vs = geo.Convex_Hull(vs);
  double ans = 0;
  UnionFind uf;
  uf.init(V);
  for(int i = 0;i < vs.size();i++){
    int j = (i + 1) % V;

    int a;
    for(a = 0;a < V;a++){
      if(gen[a] == vs[i]) break;
    }
    int b;
    for(b = 0;b < V;b++){
      if(gen[b] == vs[j]) break;
    }
    uf.unite(a,b);
    ans += (vs[i] - vs[j]).abs();
  } 
  vector<pair<double,pair<int,int>>> vec;
  for(int i = 0;i < R;i++){
    int u,v;
    cin >> u >> v;
    u--;
    v--;
    vec.push_back(make_pair((gen[u] - gen[v]).abs(),make_pair(u,v)));
  }
  sort(vec.begin(),vec.end());

  for(int i = 0;i < R;i++){
    int u = vec[i].second.first;
    int v = vec[i].second.second;
    double d = vec[i].first;
    if(uf.same(u,v)){
    }
    else{
      uf.unite(u,v);
      ans += d;
    }
  }
  cout << fixed << setprecision(10) << ans << endl;
}



Measured memory_bytes: 3308