#include <bits/stdc++.h>
using namespace std;
#define rep(n) for (int _i_i_ = (n); _i_i_; --_i_i_)
#define repf(i, st, ed) for (int i = (st); i < (ed); ++i)
#define repr(i, st, ed) for (int i = (st); i > (ed); --i)
#define rep0(i, n) for (int i = 0; i < (n); ++i)
#define rep1(i, n) for (int i = 1; i <= (n); ++i)
#define mem(arr, x) memset((arr), x, sizeof (arr))
#define mkp make_pair
#define edge(y, x, ver) for (int _i_ = h[x], y = ver[_i_]; _i_; y = ver[_i_ = nxt[_i_]])
#define rand_init mt19937 rnd(chrono::system_clock::now().time_since_epoch().count())
#define setdb(v) setprecision(v)
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
class UF {
vector<int> p, rk, sz;
int cnt;
public:
UF() {}
UF(int n) {
cnt = n;
p.resize(n);
iota(p.begin(), p.end(), 0);
rk.resize(n);
sz.resize(n);
fill(sz.begin(), sz.end(), 1);
}
int find(int x) {
return x == p[x] ? x : p[x] = find(p[x]);
}
bool merge(int x, int y) {
int fx = find(x), fy = find(y);
if (fx == fy) return false;
--cnt;
if (rk[fx] > rk[fy]) swap(fx, fy);
p[fx] = fy;
sz[fy] += sz[fx];
if (rk[fx] == rk[fy]) ++rk[fy];
return true;
}
int size() {
return cnt;
}
int size(int i) {
return sz[i];
}
};
class BIT {
vector<ll> bit;
int mx;
public:
BIT() {}
BIT(int n) {
mx = n;
bit.resize(n + 1);
}
void upd(int i, ll x) {
for (; i <= mx; i += i & -i) bit[i] += x;
}
ll ask(int i) {
ll res = 0;
for (; i; i &= i - 1) res += bit[i];
return res;
}
};
class lazySGT {
vector<int> lt, rt;
vector<ll> dat, tag;
ll v;
void spread(int k) {
if (tag[k]) {
dat[k * 2 + 1] += tag[k];
dat[k * 2 + 2] += tag[k];
tag[k * 2 + 1] = tag[k * 2 + 2] = tag[k];
tag[k] = 0;
}
}
void build(vector<ll> &a, int k, int l, int r) {
lt[k] = l, rt[k] = r, dat[k] = a[l - 1];
if (l == r) return ;
int m = (l + r) >> 1;
build(a, k * 2 + 1, l, m), build(a, k * 2 + 2, m + 1, r);
dat[k] = dat[k * 2 + 1] + dat[k * 2 + 2];
}
void update(int k, int l, int r, ll v) {
if (l <= lt[k] && rt[k] <= r) {
dat[k] += v;
tag[k] = v;
return ;
}
if (r < lt[k] || rt[k] < l) {
return ;
}
spread(k);
update(k * 2 + 1, l, r, v), update(k * 2 + 2, l, r, v);
dat[k] = dat[k * 2 + 1] + dat[k * 2 + 2];
}
ll query(int k, int l, int r) {
if (l <= lt[k] && rt[k] <= r) {
return dat[k];
}
if (r < lt[k] || rt[k] < l) {
return 0;
}
spread(k);
return query(k * 2 + 1, l, r) + query(k * 2 + 2, l, r);
}
public:
lazySGT() {}
lazySGT(vector<ll> &a) {
int n = a.size();
lt.resize(n << 3), rt.resize(n << 3);
dat.resize(n << 3), tag.resize(n << 3);
fill(dat.begin(), dat.end(), v);
build(a, 0, 1, n);
}
void update(int l, int r, ll v) {
update(0, l, r, v);
}
ll query(int l, int r) {
return query(0, l, r);
}
};
class ST {
vector<vector<ll>> arr;
public:
ST() {}
ST(vector<ll> a) {
int n = a.size();
arr.push_back(a);
int k = 31 - __builtin_clz(n);
rep1 (i, k) {
arr.push_back(vector<ll>(n - (1 << i) + 1));
rep0 (j, n - (1 << i) + 1) {
arr[i][j] = min(arr[i - 1][j], arr[i - 1][j + (1 << (i - 1))]);
}
}
}
ll query(int l, int r) {
int i = 31 - __builtin_clz(r - l + 1);
return min(arr[i][l], arr[i][r - (1 << i) + 1]);
}
};
const int maxn = 50 + 5;
int n;
int a;
void init() {
}
void clear() {
}
void solve() {
cin >> n;
int ans = 0;
rep (n) {
int mn = 1e5a;
rep (n) {
cin >> a;
mn = min(mn, a);
}
ans = max(ans, mn);
}
cout << ans << endl;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
init();
int t = 1;
//cin >> t;
rep (t) {
clear();
solve();
}
return 0;
}