#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
using namespace std;
int V,R;
const int INF2=100000000;
double EPS=1e-5;
double add(double a,double b){
	if(abs(a+b)<EPS*(abs(a)+abs(b)))return 0;
	return a+b;
}

struct P{
double x,y;
P(){x=0;y=0;}
P(double x,double y):x(x),y(y){}

P operator +(P p){
	return P(add(x,p.x),add(y,p.y));
}

bool operator ==(P p){
	return p.x==x&&p.y==y;
}

P operator -(P p){
	return P(add(x,-p.x),add(y,-p.y));
}

double det(P p){
	return add(x*p.y,-y*p.x);
}

};

P table[1000];
double edge[101][101];
bool cmp_x(const P& p,const P& q){
	if(p.x!=q.x)return p.x<q.x;
	return p.y<q.y;
}

double dist(P p,P q){
	return sqrt((p.x-q.x)*(p.x-q.x)+(p.y-q.y)*(p.y-q.y));
}
vector<P> convex_hull(P* pps,int n){



	//sort(ps,ps+n,cmp_x);

	P ps[1000];
	
	for(int i=0;i<n;i++)ps[i]=pps[i];
	int k=0;
	vector<P>qs(n*2);
	
	sort(ps,ps+n,cmp_x);

	for(int i=0;i<n;i++){

		while(true){
			if(k<=1)break;
			if((qs[k-1]-qs[k-2]).det(ps[i]-qs[k-1])>0)break;
			k--;
		}
		
			qs[k++]=ps[i];
	}

		for(int i=n-2,t=k;i>=0;i--){
		while(true){
			if(k<=t)break;
			if((qs[k-1]-qs[k-2]).det(ps[i]-qs[k-1])>0)break;
			k--;

		}
			qs[k++]=ps[i];
	}
	qs.resize(k-1);
	return qs;
}



	const int MAX_N=10000;

	int par[MAX_N];
	int rank[MAX_N];

	struct unionFind{


		unionFind(int n){
			for(int i=0;i<n;i++){
				par[i]=i;
				rank[i]=0;
			}
		}

		int find(int x){
			if(par[x]==x){
				return x;
			}	
			else {
			return 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 ed{
int u,v;double cost;
ed(){
	u=0;v=0;cost=0;
}
ed(int u,int v,double cost){
	u=u;
	v=v;
	cost=cost;
}
};

bool cmp(ed a,ed b){
	return a.cost<b.cost;
}

bool used[1000];
	ed es[2000];
int main(){
	
	cin>>V>>R;
	for(int i=0;i<V;i++){
		cin>>table[i].x>>table[i].y;
		
	}

	int cnt=0;

	for(int i=0;i<V;i++)for(int j=0;j<V;j++)if(i!=j)edge[i][j]=edge[j][i]=INF2;

	for(int i=0;i<R;i++){
		int a,b;
		cin>>a>>b;
		
		edge[a-1][b-1]=dist(P(table[a-1]),P(table[b-1]));
		edge[b-1][a-1]=dist(P(table[a-1]),P(table[b-1]));

		ed aa;
		aa.u=a-1;aa.v=b-1;aa.cost=dist(P(table[a-1]),P(table[b-1]));
		es[i]=aa;

		//cout<<es[i].u<<" "<<es[i].v<<endl;
	}


	vector<P>a;
	a=convex_hull(table,V);

	for(int i=0;i<V;i++){
		for(int j=0;j<a.size();j++){
			if(table[i].x==a[j].x&&table[i].y==a[j].y){
			used[i]=1;
			}
		}
	}	

	unionFind uni(1000);

	for(int i=0;i<V;i++){
		for(int j=0;j<V;j++){
			if(used[i]&&used[j]){
					edge[i][j]=dist(table[i],table[j]);
					edge[j][i]=dist(table[i],table[j]);
					uni.unite(i,j);
			}
		}
	}


	double ans=0;
	
	for(int i=1;i<a.size();i++){
		ans+=dist(a[i],a[i-1]);
		}

	if(a.size()>=1)ans+=dist(a[0],a[a.size()-1]);

	sort(es,es+R,cmp);
	//for(int i=0;i<R;i++)cout<<es[i].u<<" "<<es[i].v<<endl;

	for(int i=0;i<R;i++){
	//cout<<"X"<<endl;
		ed e=es[i];
		if(!uni.same(e.u,e.v)){
			//cout<<e.u<<" "<<e.v<<endl;
			uni.unite(e.u,e.v);
			ans+=e.cost;
			//cout<<"Y"<<endl;
		}	
	}
	
	
	cout<<fixed<<ans<<endl;
	return 0;
}

Measured memory_bytes: 3468