#include <bits/stdc++.h>
using namespace std;
const int N=100+5,INF=1<<30;
int n;
int edge[N][N];
int ex_left[N],ex_right[N];
bool vis_left[N],vis_right[N];
int match[N];
int min_change;
bool dfs(int left)
{
vis_left[left]=true;
for(int right=1;right<=n;++right){
if(vis_right[right]||!edge[left][right]) continue;
int gap=ex_left[left]+ex_right[right]-edge[left][right];
if(!gap) {
vis_right[right]=true;
if(!match[right]||dfs(match[right])){
match[right]=left;
return true;
}
}
else min_change=min(min_change,gap);
}
return false;
}
int KM()
{
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
ex_left[i]=max(ex_left[i],edge[i][j]);
for(int i=1;i<=n;++i)
{
min_change=INF;
while(true)
{
memset(vis_left,0,sizeof(vis_left));
memset(vis_right,0,sizeof(vis_right));
if(dfs(i)) break;
for(int j=1;j<=n;++j){
if(vis_left[j]) ex_left[j]-=min_change;
if(vis_right[j]) ex_right[j]+=min_change;
}
}
}
int res=0;
for(int i=1;i<=n;++i)
res+=edge[match[i]][i];
return res;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
scanf("%d",&edge[i][j]);
int ans1=KM();
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
edge[i][j]=-edge[i][j];
for(int i=1;i<=n;++i)
ex_left[i]=-INF,
ex_right[i]=match[i]=0;
printf("%d\n%d",-KM(),ans1);
return 0;
}