//#define NDEBUG

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <chrono>
#include <iostream>
#include <vector>
#include "boost/multi_array.hpp"

struct EndDistances;
using CityId = unsigned;
using DistanceType = unsigned;
using StoredDistanceType = unsigned char;
using CacheDistanceType = EndDistances;
using DistanceArray = boost::multi_array<DistanceType, 2>;

template<std::size_t size>
std::ostream& operator<<(std::ostream& out, const unsigned(& v)[size]) {
        out << '{';
    for(unsigned i=0; i<size; i++)
        out << v[i]<<',';
    return out << '}';
}
std::ostream& operator<<(std::ostream& out, const std::vector<unsigned>& v) {
        out << '{';
    for(unsigned i=0; i<v.size(); i++)
        out << v[i]<<',';
    return out << '}';
}
std::ostream& operator<<(std::ostream& out, const boost::detail::multi_array::sub_array<unsigned,1>& v) {
        out << '{';
    for(unsigned i=0; i<v.size(); i++)
        out << v[i]<<',';
    return out << '}';
}

struct EndDistances {
    StoredDistanceType dists[7];
};
class TspCache {
    std::vector<CacheDistanceType> cache;
public:
    std::size_t size() {return cache.size();}
    void assertEmpty(std::size_t idx) {assert(idx>=cache.size() || cache[idx].dists[0]==0);}
    void put(std::size_t idx, CacheDistanceType distance) {if(cache.size()<=idx)cache.resize(idx+1); cache[idx] = distance;}
    const CacheDistanceType& get(std::size_t idx) { assert(idx<cache.size()); return cache[idx];}
};

class TspSolver {
    using OrderIdx = unsigned;
    using OrderedCityArray = boost::multi_array<CityId, 2>;
    
    unsigned city_count;
    DistanceArray distances;
    OrderedCityArray closest_cities;
    TspCache end_cache;
    DistanceType best_end_distance;
    
    std::vector<CityId> current_cities;
    unsigned current_count;
    unsigned visited;
    DistanceType current_distance;
    std::vector<CityId> best_cities;
    DistanceType best_distance;
    
    void calculate_closest_cities() {
        closest_cities.resize(boost::extents[city_count][city_count]);
        for(CityId i=0; i<city_count; i++) {
            for(CityId j=0; j<city_count; j++)
                closest_cities[i][j] = j;
            auto comp = [&](CityId l, CityId r){
                if(l>0 && r>0) return distances[i][l] < distances[i][r];
                return l>0;
            };
            std::sort(closest_cities[i].begin(), closest_cities[i].end(), comp);
        }
    }
    template<unsigned k>
    static unsigned n_choose_k(unsigned n) {
        if (k > n) return 0;
        if (k == n) return 1;
        unsigned long long result = 1;
        for( unsigned i = 1; i <= k; ++i ) {
            result *= (n-i+1);
            result /= i;
        }
        return result;
    }
    DistanceType find_end_distance(CityId* cities, DistanceType abortDistance) {
        //assert(std::cout << "find_end_distance "<< cities[0] << ',' << cities[1] << ',' << cities[2]  << ',' << cities[3]  << ',' << cities[4]  << ',' << cities[5] << " abortDistance="<<abortDistance<<std::flush);
        assert(std::is_sorted(cities+1, cities+6));
        DistanceType local_min = std::numeric_limits<DistanceType>::max();
        std::array<CityId, 6> best;
        do {
            DistanceType dist = distances[cities[0]][cities[1]] 
                + distances[cities[1]][cities[2]]
                + distances[cities[2]][cities[3]] 
                + distances[cities[3]][cities[4]]
                + distances[cities[4]][cities[5]]
                + distances[cities[5]][0];
            if (dist == abortDistance) {                
                //assert(std::cout << " found="<< cities[0] << ',' << cities[1] << ',' << cities[2]  << ',' << cities[3]  << ',' << cities[4]  << ',' << cities[5]<<'\n'<<std::flush);
                return abortDistance;
            }
            if (dist < local_min) {
                local_min = dist;
                std::copy(cities, cities+6, best.begin());
            }
        } while(std::next_permutation(cities+0, cities+6));
        std::copy(best.begin(), best.end(), cities);
        //assert(std::cout << " local_min="<<local_min<<'\n'<<std::flush);
        return local_min;
    }
    void fill_cache() {
        //assert(n_choose_k<7>(64) == 621216192);
        best_end_distance = std::numeric_limits<DistanceType>::max();
        unsigned count = 0;
        for(CityId a=7; a<city_count; a++) {
            unsigned ai = a-7;
            unsigned am = n_choose_k<7>(a-1);
            unsigned aa = 0+am;
            for(CityId b=1; b<a; b++) {
                unsigned bi = b-6;
                unsigned bm = n_choose_k<6>(b-1);
                unsigned ba = aa+bm;
                for(CityId c=1; c<b; c++) {
                    unsigned ci = c-1;
                    unsigned cm = n_choose_k<5>(c-1);
                    unsigned ca = ba+cm;
                    for(CityId d=1; d<c; d++) {
                        unsigned di = d-1;
                        unsigned dm = n_choose_k<4>(d-1);
                        unsigned da = ca+dm;
                        for(CityId e=1; e<d; e++) {
                            unsigned ei = e-1;
                            unsigned em = n_choose_k<3>(e-1);
                            unsigned ea = da+em;
                            for(CityId f=1; f<e; f++) {
                                unsigned fi = f-1;
                                unsigned fm = n_choose_k<2>(f-1);
                                unsigned fa = ea+fm;
                                for(CityId g=1; g<f; g++) {
                                    unsigned gi = g-1;
                                    unsigned gm = gi; // n_choose_k<1>(g-1) is always g-1;
                                    unsigned ga = fa+gm;
                                    assert(std::cout << "fill_cache offsets=" <<ai<<'x'<<am << ',' <<bi<<'x'<<bm<< ',' <<ci<<'x'<<cm  << ',' <<di<<'x'<<dm  << ',' <<ei<<'x'<<em  << ',' <<fi<<'x'<<fm  << ',' <<gi<<'x'<<gm<<" ga="<<ga<<'\n' << std::flush);
                                    std::array<CityId,6> cities = {{g, f, e, d, c, b}};
                                    EndDistances ends;
                                    ends.dists[0] = find_end_distance(cities.data(), 0);
                                    ends.dists[0] += distances[a][cities[0]];
                                    cities = {{g, f, e, d, c, a}};
                                    ends.dists[1] = find_end_distance(cities.data(), 0);
                                    ends.dists[1] += distances[b][cities[0]];
                                    cities = {{g, f, e, d, b, a}};
                                    ends.dists[2] = find_end_distance(cities.data(), 0);
                                    ends.dists[2] += distances[c][cities[0]];
                                    cities = {{g, f, e, c, b, a}};
                                    ends.dists[3] = find_end_distance(cities.data(), 0);
                                    ends.dists[3] += distances[d][cities[0]];
                                    cities = {{g, f, d, c, b, a}};
                                    ends.dists[4] = find_end_distance(cities.data(), 0);
                                    ends.dists[4] += distances[d][cities[0]];
                                    cities = {{g, e, d, c, b, a}};
                                    ends.dists[5] = find_end_distance(cities.data(), 0);
                                    ends.dists[5] += distances[f][cities[0]];
                                    cities = {{f, e, d, c, b, a}};
                                    ends.dists[6] = find_end_distance(cities.data(), 0);
                                    ends.dists[6] += distances[g][cities[0]];
                                    assert(std::cout << "fill_cache " << a << ',' << b << ',' << c  << ',' << d  << ',' << e  << ',' << f  << ',' << g << " idx=" << ga << '\n' << std::flush);
                                    end_cache.assertEmpty(ga);
                                    end_cache.put(ga, ends);
                                    assert(end_cache.get(ga).dists[0]>0);
                                    ++count;
                                    DistanceType local_min = *std::min(ends.dists+0, ends.dists+7);
                                    if (local_min<best_end_distance)
                                        best_end_distance = local_min;
                                }
                            }
                        }
                    }
                }
            }
        }
        std::cout << "Using " << (count*sizeof(CacheDistanceType)) << " out of " << (end_cache.size()*sizeof(CacheDistanceType)) << " allocated bytes\n";// << std::flush; 
        assert(std::cout << "fill_cache best_end_distance=" << best_end_distance << '\n' << std::flush);
    }
    void solve_end_fast() {
        unsigned remain = visited;
        CityId prev = current_cities[city_count-8];
        assert(std::cout << "solve_end_fast  count=" << current_count << " current=" << current_cities << " dist=" << current_distance << " prev_city=" << prev << " prev_visited="<<std::bitset<32>(visited)<<std::flush);
        CityId* remainingIds = current_cities.data()+city_count-7;
        CityId& a = remainingIds[0];
        CityId& b = remainingIds[1];
        CityId& c = remainingIds[2];
        CityId& d = remainingIds[3];
        CityId& e = remainingIds[4];
        CityId& f = remainingIds[5];
        CityId& g = remainingIds[6];
        a = 31-__builtin_clz(remain);
        remain &= ~(1u<<a);
        b = 31-__builtin_clz(remain);
        remain &= ~(1u<<b);
        c = 31-__builtin_clz(remain);
        remain &= ~(1u<<c);
        d = 31-__builtin_clz(remain);
        remain &= ~(1u<<d);
        e = 31-__builtin_clz(remain);
        remain &= ~(1u<<e);
        f = 31-__builtin_clz(remain);
        remain &= ~(1u<<f);
        g = 31-__builtin_clz(remain);
        assert(std::cout << " remaining="<< a << ',' << b << ',' << c  << ',' << d  << ',' << e  << ',' << f  << ',' << g << std::flush);
            unsigned ai = a-7;
            unsigned am = n_choose_k<7>(a-1);
            unsigned aa = 0+am;
                unsigned bi = b-6;
                unsigned bm = n_choose_k<6>(b-1);
                unsigned ba = aa+bm;
                    unsigned ci = c-1;
                    unsigned cm = n_choose_k<5>(c-1);
                    unsigned ca = ba+cm;
                        unsigned di = d-1;
                        unsigned dm = n_choose_k<4>(d-1);
                        unsigned da = ca+dm;
                            unsigned ei = e-1;
                            unsigned em = n_choose_k<3>(e-1);
                            unsigned ea = da+em;
                                unsigned fi = f-1;
                                unsigned fm = n_choose_k<2>(f-1);
                                unsigned fa = ea+fm;
                                    unsigned gi = g-1;
                                    unsigned gm = gi; // n_choose_k<1>(g-1) is always g-1;
                                    unsigned ga = fa+gm;
        assert(std::cout << " offsets=" <<ai<<'x'<<am << ',' <<bi<<'x'<<bm<< ',' <<ci<<'x'<<cm  << ',' <<di<<'x'<<dm  << ',' <<ei<<'x'<<em  << ',' <<fi<<'x'<<fm  << ',' <<gi<<'x'<<gm<<" ga="<<ga << std::flush);
        const EndDistances& end_dist_array = end_cache.get(ga);
        assert(end_dist_array.dists[0]>0);
        EndDistances new_dist_array = {{
            static_cast<StoredDistanceType>(current_distance + distances[prev][a] + end_dist_array.dists[0]),
            static_cast<StoredDistanceType>(current_distance + distances[prev][b] + end_dist_array.dists[1]),
            static_cast<StoredDistanceType>(current_distance + distances[prev][c] + end_dist_array.dists[2]),
            static_cast<StoredDistanceType>(current_distance + distances[prev][d] + end_dist_array.dists[3]),
            static_cast<StoredDistanceType>(current_distance + distances[prev][e] + end_dist_array.dists[4]),
            static_cast<StoredDistanceType>(current_distance + distances[prev][f] + end_dist_array.dists[5]),
            static_cast<StoredDistanceType>(current_distance + distances[prev][g] + end_dist_array.dists[6]),
        }};
        assert(std::cout << " dists="<<+end_dist_array.dists[0]<<','<<+end_dist_array.dists[1]<<','<<+end_dist_array.dists[2]<<','<<+end_dist_array.dists[3]<<','<<+end_dist_array.dists[4]<<','<<+end_dist_array.dists[5]<<','<<+end_dist_array.dists[6] << std::flush);
        unsigned best_idx = std::min_element(new_dist_array.dists+0, new_dist_array.dists+7)-new_dist_array.dists+0;
        DistanceType end_dist = end_dist_array.dists[best_idx];
        DistanceType new_dist = new_dist_array.dists[best_idx];
        assert(std::cout << " best_idx="<< best_idx << " first="<<remainingIds[best_idx]<<" end_dist=" << end_dist << " new_dist=" << new_dist << std::flush);
        if (new_dist >= best_distance) {
            assert(std::cout << " - exit because " <<  new_dist << ">=" << best_distance << '\n' << std::flush);
            return;
        }
        assert(std::cout << '\n'<<std::flush);
        assert(std::cout << "solve_end_slow  beforeRotate=" << current_cities << '\n' << std::flush);
        if (best_idx>0)
            std::rotate(remainingIds+0, remainingIds+best_idx,remainingIds+best_idx+1);
        std::reverse(remainingIds+1, remainingIds+7);
        assert(std::cout << "solve_end_slow  afterRotate=" << current_cities << '\n' << std::flush);
        find_end_distance(&current_cities[city_count-7], end_dist);
        assert(std::cout << "solve_end_slow  " << current_cities << " new best because " << new_dist << "<" << best_distance << '\n' << std::flush);
        best_cities = current_cities;
        best_distance = new_dist;
    }
    void solve_recursive() {
        unsigned prev_count = current_count;
        DistanceType prev_distance = current_distance;
        unsigned prev_visited = visited;
        CityId prev_city = current_cities[current_count-1];
        assert(std::cout << "solve_recursive count=" << prev_count << " current=" << current_cities << " dist=" << prev_distance << " prev_city=" << prev_city << " prev_visited="<<std::bitset<32>(prev_visited)<<" closest=" << closest_cities[prev_city] << '\n' << std::flush);
        ++current_count;
        for(OrderIdx i=0; i<city_count; i++) {
            CityId c = closest_cities[prev_city][i];
            if ((visited & (1u<<c)) == 0) continue;
            current_cities[prev_count] = c;
            current_distance = prev_distance + distances[prev_city][c];
            if (current_distance + best_end_distance >= best_distance) {
                assert(std::cout << "solve_recursive     skip " << c << " because " <<  current_distance << " + " << best_end_distance << " >= " << best_distance << '\n' << std::flush);
                continue;
            }
            visited = prev_visited & ~(1u<<c);
            if (current_count == city_count-7)
                solve_end_fast();
            else
                solve_recursive();
        }
        current_count = prev_count;
    }
public:
    TspSolver(DistanceArray distances_) 
    : distances(std::move(distances_)) 
    {
        city_count = distances.size();
        calculate_closest_cities();
        fill_cache();
    }
    
    std::vector<CityId> solve() {
        current_cities.resize(city_count + 1, 0);
        current_count = 1;
        current_distance = 0;
        visited = (1u<<city_count)-2u;
        best_cities.resize(city_count + 1, 0);
        best_distance = std::numeric_limits<DistanceType>::max();
        solve_recursive();
        return best_cities;
    }
};

DistanceArray get_distances() {
    std::istream& in = std::cin;
    unsigned city_count;
    in >> city_count;
    DistanceArray distances(boost::extents[city_count][city_count]);
    for(CityId i=0; i<city_count-1; i++) {
        distances[i][i] = std::numeric_limits<DistanceType>::max();
        for(CityId j=i+1; j<city_count; j++) {
            in >> distances[i][j];
            distances[j][i] = distances[i][j];
        }
    }
    assert(in);
    return distances;
}

int main() {
    auto start = std::chrono::high_resolution_clock::now();
    TspSolver solver(get_distances());
    std::vector<unsigned> cities = solver.solve();
    auto end = std::chrono::high_resolution_clock::now();
    for(CityId i=0; i<cities.size(); i++)
        std::cout << cities[i] << ',';
    std::cout << ' ' << duration_cast<std::chrono::milliseconds>(end-start).count() << "ms\n";
}
    
10 6 7 2 2 7 3 4 8 2 2 6 4 5 5 5 3 6 6 5 6 5 4 2 6 2 8 4 3 6 2 6 3 3 7 3 3 6 8 5 6 9 3 6 6 11 