#include <iostream>
#include <vector>
#include <tuple>
#include <algorithm>
#include <functional>
#include <numeric>
using namespace std;
using T = tuple<int, int, int>;
int main(int argc, char const *argv[]) {
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin >> n;
vector<vector<int>> mat(n, vector<int>(n));
for (int u = 0; u < n; ++u)
for (int v = 0; v < n; ++v) cin >> mat[u][v];
vector<T> edges;
for (int u = 0; u < n; ++u)
for (int v = u + 1; v < n; ++v)
edges.emplace_back(u, v, mat[u][v]);
sort(begin(edges), end(edges), [](const auto& e1, const auto& e2) {
return get<2>(e1) < get<2>(e2);
});
vector<int> p(n);
iota(begin(p), end(p), 0);
function<int(int)> find = [&](int x) -> int {
return p[x] = p[x] ^ x ? find(p[x]) : x;
};
auto merge = [&](int u, int v) -> void {
p[find(u)] = p[find(v)];
};
auto isConnected = [&](int u, int v) -> bool {
return find(u) == find(v);
};
int cnt = 0, mst = 0, u, v, w;
for (const auto& e : edges) {
u = get<0>(e), v = get<1>(e), w = get<2>(e);
if (isConnected(u, v)) continue;
merge(u, v);
mst += w;
if (++cnt == n - 1) {
cout << mst << endl;
return 0;
}
}
return 0;
}