const int MAX_MEM = 1.3e8;
size_t mpos = 0;
char mem[MAX_MEM];
inline void* operator new(size_t n) {
char *res = mem + mpos;
mpos += n;
return res;
}
inline void operator delete (void *) {
}
//
// Stvoreno Energom o 24.10.23. 14:22:07
//
#include <bits/stdc++.h>
#define F first
#define S second
#define MP make_pair
#define PB push_back
#define all(a) a.begin(), a.end()
#define len(a) (int) (a.size())
#define fir first
#define sec second
#define mp make_pair
#define pb push_back
using namespace std;
#ifdef Energy_is_not_over
#define DEBUG for (int _____DEBUG=1;_____DEBUG;_____DEBUG=0)
#define LOG(...) print(#__VA_ARGS__" ::",__VA_ARGS__)<<endl
template<class ...Ts>
auto &print(Ts ...ts) { return ((cerr << ts << " "), ...); }
#else
#define DEBUG while (0)
#define LOG(...)
#endif
typedef pair<int, int> pii;
typedef long long ll;
typedef long double ld;
const int max_n = 2000+10, inf = 1000111222;
int last=0;
int l[max_n];
int r[max_n];
int new_node()
{
return ++last;
}
pair<pii,int> leaf[2*max_n];
double dist[max_n][max_n];
int build_tree(vector<pair<pii,int>> v,int type)
{
int res=new_node();
if (len(v)==1){
LOG(res,v[0].fir.fir,v[0].fir.sec,v[0].sec);
leaf[res]=v[0];
return res;
}
if (type==0){
sort(all(v),[&](const pair<pii,int>& lhs,const pair<pii,int>& rhs){
return lhs.fir.fir<rhs.fir.fir;
});
}
else{
sort(all(v),[&](const pair<pii,int>& lhs,const pair<pii,int>& rhs){
return lhs.fir.sec<rhs.fir.sec;
});
}
l[res]=build_tree({v.begin(),v.begin()+len(v)/2},type^1);
r[res]=build_tree({v.begin()+len(v)/2,v.end()},type^1);
return res;
}
vector<int> all_down[max_n];
vector<pii> all_pairs[max_n];
double dp[max_n][max_n];
pair<int,int> dp_pred[max_n][max_n];
double pr_dp[max_n][max_n];
pair<int,int> pr_dp_pred[max_n][max_n];
void build_dp(int now)
{
if (l[now]==0 && r[now]==0){
all_down[now].pb(leaf[now].sec);
all_pairs[now].pb(mp(leaf[now].sec,leaf[now].sec));
dp[leaf[now].sec][leaf[now].sec]=0;
return;
}
build_dp(l[now]);
for (auto i:all_down[l[now]]){
all_down[now].pb(i);
}
build_dp(r[now]);
for (auto i:all_down[r[now]]){
all_down[now].pb(i);
}
for (auto k1:all_down[l[now]]){
for (auto k2:all_down[r[now]]){
all_pairs[now].pb(mp(k1,k2));
all_pairs[now].pb(mp(k2,k1));
}
}
for (int iter=0;iter<2;iter++){
for (auto [st1,fn1]:all_pairs[l[now]]){
for (auto st2:all_down[r[now]]){
if (pr_dp[st1][st2]>dp[st1][fn1]+dist[fn1][st2]){
pr_dp[st1][st2]=dp[st1][fn1]+dist[fn1][st2];
pr_dp_pred[st1][st2]=mp(fn1,iter);
}
}
}
for (auto st1:all_down[l[now]]){
for (auto [st2,fn2]:all_pairs[r[now]]){
if (dp[st1][fn2]>pr_dp[st1][st2]+dp[st2][fn2]){
dp[st1][fn2]=pr_dp[st1][st2]+dp[st2][fn2];
dp_pred[st1][fn2]=mp(st2,iter);
}
}
}
swap(l[now],r[now]);
}
}
vector<int> ans;
void restore_ans(int now,pii wanted_pair)
{
if (l[now]==0 && r[now]==0){
ans.pb(leaf[now].sec);
return;
}
if (wanted_pair==mp(-1,-1)){
for (auto i:all_pairs[now]){
if (wanted_pair==mp(-1,-1) || dp[i.fir][i.sec]<dp[wanted_pair.fir][wanted_pair.sec]){
wanted_pair=i;
}
}
}
pii st2_and_iter=dp_pred[wanted_pair.fir][wanted_pair.sec];
pii fn1_and_iter=pr_dp_pred[wanted_pair.fir][st2_and_iter.fir];
if (st2_and_iter.sec){
swap(l[now],r[now]);
}
restore_ans(l[now],mp(wanted_pair.fir,fn1_and_iter.fir));
restore_ans(r[now],mp(st2_and_iter.fir,wanted_pair.sec));
}
int main() {
// freopen("input_l.txt","r",stdin);
// freopen("output.txt","w",stdout);
ios_base::sync_with_stdio(0);
cin.tie(0);
for (int i=0;i<max_n;i++){
for (int j=0;j<max_n;j++){
dp[i][j]=1e18;
pr_dp[i][j]=1e18;
}
}
int n;
cin>>n;
if (n==1){
cout<<fixed<<setprecision(10)<<0<<"\n";
cout<<1<<"\n";
return 0;
}
vector<pair<pii,int>> xy(n);
for (int i=0;i<n;i++){
cin>>xy[i].fir.fir>>xy[i].fir.sec;
xy[i].sec=i;
}
for (int i=0;i<n;i++){
for (int j=0;j<n;j++){
int dx=xy[i].fir.fir-xy[j].fir.fir;
int dy=xy[i].fir.sec-xy[j].fir.sec;
dist[i][j]=sqrtl(1ll*dx*dx+1ll*dy*dy);
}
}
int root=build_tree(xy,0);
build_dp(root);
restore_ans(root,mp(-1,-1));
ld res=0;
for (int i=0;i+1<len(ans);i++){
res+=dist[ans[i]][ans[i+1]];
}
cout<<fixed<<setprecision(10)<<res<<"\n";
for (auto i:ans){
cout<<i+1<<" ";
}
cout<<"\n";
return 0;
}