#include <bits/stdc++.h>
using namespace std;
inline long long in() {
  int32_t x;
  scanf("%d", &x);
  return x;
}
inline string getStr() {
  char ch[1000000];
  scanf("%s", ch);
  return ch;
}
inline char getCh() {
  char ch;
  scanf(" %c", &ch);
  return ch;
}
const long long MAX_N = 2005;
const long long INF = 1e18;
const long long MAX_LG = 13;
struct edge {
  long long v, u, w;
  edge() {}
  edge(long long v, long long u, long long w) : v(v), u(u), w(w) {}
};
struct connection {
  long long u, w;
  connection() {}
  connection(long long u, long long w) : u(u), w(w) {}
  connection(long long u) : u(u), w(1) {}
};
long long pr[MAX_N], sz[MAX_N], di[MAX_N][MAX_N], lvl[MAX_N],
    root[MAX_N][MAX_LG], cst[MAX_N], di2[MAX_N][MAX_N];
inline long long find(long long p) {
  return (pr[p] == p ? p : pr[p] = find(pr[p]));
}
vector<connection> g[MAX_N];
inline void dfs(long long node, long long prev, long long h = 0,
                long long cost = 0) {
  root[node][0] = prev;
  lvl[node] = h;
  cst[node] = cost;
  for (long long i = 1; i < MAX_LG; i++)
    root[node][i] = root[root[node][i - 1]][i - 1];
  for (long long i = 0; i < g[node].size(); i++) {
    long long u = g[node][i].u;
    if (u != prev) dfs(u, node, h + 1, (long long)cost + g[node][i].w);
  }
}
inline long long lca(long long p, long long q) {
  if (lvl[p] < lvl[q]) swap(p, q);
  for (long long i = MAX_LG - 1; i >= 0; i--)
    if (lvl[p] - lvl[q] >= (1 << i)) p = root[p][i];
  if (p == q) return p;
  for (long long i = MAX_LG - 1; i >= 0; i--)
    if (root[q][i] != root[p][i] && lvl[p] >= (1 << i))
      p = root[p][i], q = root[q][i];
  return root[p][0];
}
vector<edge> e;
inline bool cmp(const edge &a, const edge &b) { return a.w < b.w; }
int32_t main() {
  long long n = in();
  for (long long i = 0; i < MAX_N; i++) pr[i] = i, sz[i] = 1;
  for (long long i = 0; i < n; i++) {
    for (long long j = 0; j < n; j++) {
      di[i][j] = in();
      if (i != j && di[i][j] == 0) return cout << "NO\n", 0;
      if (i == j && di[i][j]) return cout << "NO\n", 0;
      if (i != j) e.push_back(edge(i, j, di[i][j]));
    }
  }
  sort(e.begin(), e.end(), cmp);
  for (long long i = 0; i < e.size(); i++) {
    long long u = e[i].u;
    long long v = e[i].v;
    long long vl = e[i].w;
    u = find(u), v = find(v);
    if (u == v) continue;
    if (sz[u] < sz[v]) swap(u, v);
    pr[v] = u;
    if (sz[u] == sz[v]) sz[u]++;
    g[e[i].u].push_back(connection(e[i].v, vl));
    g[e[i].v].push_back(connection(e[i].u, vl));
  }
  dfs(0, 0);
  for (long long i = 0; i < n; i++) {
    for (long long j = 0; j < n; j++) {
      long long val = di[i][j];
      long long LCA = lca(i, j);
      if (i == j) continue;
      long long shouldBeWhat = cst[i] + 1LL * cst[j] - 2 * cst[LCA];
      if (shouldBeWhat != val) return cout << "NO\n", 0;
    }
  }
  cout << "YES" << endl;
}
