#include <cstdio>
#include <vector>
#include <algorithm>
#include <queue>
#include <climits>
using namespace std;
const int nmax = 200;
struct Muchie {
int to, rev, flow, cap, cost;
};
struct Nod {
int nod, cost;
bool operator > (Nod other) const {
return cost > other.cost;
}
};
int n, src, dest;
vector <Muchie> g[5 + nmax];
int dist[5 + nmax], distdij[5 + nmax], prevnode[5 + nmax], prevedge[5 + nmax], prevflow[5 + nmax];
void bellmanford() {
fill(dist, dist + dest + 1, INT_MAX);
queue <int> q;
q.push(src);
dist[src] = 0;
while(!q.empty()) {
int from = q.front();
for(int k = 0; k < g[from].size(); ++ k) {
Muchie& e = g[from][k];
if(e.flow < e.cap && dist[from] + e.cost < dist[e.to]) {
dist[e.to] = dist[from] + e.cost;
q.push(e.to);
}
}
q.pop();
}
}
bool viz[5 + nmax];
void dijkstra() {
fill(viz, viz + dest + 1, 0);
fill(distdij, distdij + dest + 1, INT_MAX);
priority_queue <Nod, vector<Nod>, greater<Nod>> q;
q.push({src, 0});
prevflow[src] = INT_MAX;
distdij[src] = 0;
while(!q.empty()) {
int from = q.top().nod;
if(viz[from] == 0) {
viz[from] = 1;
for(int k = 0; k < g[from].size(); ++ k) {
Muchie& e = g[from][k];
int aux = distdij[from] + dist[from] - dist[e.to] + e.cost;
if(e.flow < e.cap && aux < distdij[e.to]) {
distdij[e.to] = aux;
q.push({e.to, aux});
prevnode[e.to] = from;
prevedge[e.to] = k;
prevflow[e.to] = min(prevflow[from], e.cap - e.flow);
}
}
}
q.pop();
}
}
int mincutflow() {
int cost = 0;
bellmanford();
dijkstra();
while(distdij[dest] < INT_MAX) {
int deltaFlow = prevflow[dest];
for(int i = dest; i != src; i = prevnode[i]) {
Muchie& e = g[prevnode[i]][prevedge[i]];
e.flow += deltaFlow;
g[e.to][e.rev].flow -= deltaFlow;
cost += deltaFlow * e.cost;
}
for(int i = 0; i <= dest; ++ i) {
dist[i] += distdij[i];
}
dijkstra();
}
return cost;
}
int main() {
freopen("cc.in", "r", stdin);
freopen("cc.out", "w", stdout);
scanf("%d", &n);
dest = n + n + 1;
for(int i = 1; i <= n; ++ i) {
for(int j = 1; j <= n; ++ j) {
int x;
scanf("%d", &x);
g[i].push_back({j + n, g[j + n].size(), 0, 1, x});
g[j + n].push_back({i, g[i].size() - 1, 0, 0, -x});
}
}
for(int i = 1; i <= n; ++ i) {
g[src].push_back({i, g[i].size(), 0, 1, 0});
g[i].push_back({src, g[src].size() - 1, 0, 0, 0});
}
for(int i = 1; i <= n; ++ i) {
g[i + n].push_back({dest, g[dest].size(), 0, 1, 0});
g[dest].push_back({i + n, g[i + n].size() - 1, 0, 0, 0});
}
printf("%d\n", mincutflow());
return 0;
}