#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef pair<double,ll> mp;
#define inf 1e9
#define EPS 1e-10
struct point{
    double x,y;
    point(){}
    point(double x,double y):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) ; }
    double norm() { return x*x + y*y;}
    double abs() { return sqrt(norm());}
    void input() { cin>>x>>y; }
    bool operator < (point p) { return x!=p.x ? x <p.x : y < p.y ;}
    bool operator == (point p) { return x==p.x && y==p.y ; }
};
bool sort_y(point a,point b){
    return a.y != b.y ? a.y < b.y : a.x < b.x;
}
double dot(point a,point b){ return a.x*b.x + a.y * b.y ;}
double cross(point a,point b){ return a.x*b.y-a.y*b.x; }
int ccw(point p0,point p1,point p2){
    point a = p1-p0;
    point b = p2-p0;
    if(cross(a,b)  > EPS) return 1;
    if(cross(a,b) < -EPS) return -1;
    if(dot(a,b) < -EPS ) return 2;
    if(a.norm() < b.norm() ) return -2;
    return 0;
}

typedef vector<point> polygon;
polygon andrewscan(polygon ps){
    polygon u,l;
    if(ps.size() < 3) return ps;
    sort(ps.begin(),ps.end() ,sort_y);
    u.push_back(ps[0]);
    u.push_back(ps[1]);
    l.push_back(ps[ps.size()-1]);
    l.push_back(ps[ps.size()-2]);
    for(int i=2;i<ps.size();i++){
	for(int n = u.size();n>=2&&ccw(u[n-2],u[n-1],ps[i] ) == 1; n-- )u.pop_back();
	u.push_back(ps[i]);
    }
    for(int i=ps.size()-3;i>=0;i--){
	for(int n=l.size();n>=2&&ccw(l[n-2],l[n-1],ps[i]) ==1 ;n--)l.pop_back();
		l.push_back(ps[i]);
    }
    reverse(l.begin(),l.end() );
    for(int i=u.size()-2;i>=1;i--) l.push_back( u[i] );
    return l;
}

int main(){
	int v,r;
	cin>>v>>r;
	polygon ps(v);
	for(int i=0;i<v;i++) ps[i].input();
	vector<vector<mp> > g(v);
	for(int i=0;i<r;i++){
	    int s,t;
	    cin>>s>>t;
	    s--,t--;
	    g[s].push_back(mp( ( ps[s]-ps[t]).abs() ,t) );
	    g[t].push_back(mp( (ps[s]-ps[t] ).abs() ,s) );
	}
	/*for(int i=0;i<v;i++){
	    for(int j=0;j<g[i].size();j++){
		cout<<g[i][j].first<<' '<<g[i][j].second<<':';
	    }
	    cout<<endl;
	}*/
	polygon res = andrewscan(ps);
	vector<bool> used(v,false);
	ll cnt =0;
	double ans = 0;
	priority_queue<mp,vector<mp>,greater<mp> > q;
	for(int i=0;i<res.size();i++) ans += ( res[i] - res[(i+1)%res.size()] ).abs();
	for(int i=0;i<res.size();i++){
	    for(int j=0;j<v;j++){
		if( res[i].x ==ps[j].x && res[i].y == ps[j].y ){
		    used[j] = true;
		    for(int k = 0;k<g[j].size();k++){
			q.push(g[j][k]);
		    }
		    break;
		}
	    }
	}

	/*for(int i=0;i<v;i++){
	    if(used[i])cout<<i<<endl;
	}*/
	//for(int i=0;i<res.size();i++)cout<<' '<<res[i].x<<' '<<res[i].y<<endl;
	//cout<<ans<<endl;
	while( !q.empty() && cnt != v){
	    mp now = q.top();
	    q.pop();
	    ll nn = now.second;
	    double cost = now.first;
	 //   cout<<nn<<' '<<cost<<endl;
	    if(used[nn])continue;
	 //   cout<<"OK"<<endl;
	    used[nn] = true;
	    ans+= cost;
	    for(int i=0;i<g[nn].size();i++){
		ll next = g[nn][i].second;
		if(used[next])continue;
		q.push(g[nn][i]);
	    }
	}
	printf("%0.10lf\n",ans);
	return 0;
}

