#include <bits/stdc++.h>
using namespace std;
template <class T, class U>
void maximize(T &x, U y) {
  if (x < y) x = y;
}
template <class T, class U>
void minimize(T &x, U y) {
  if (x > y) x = y;
}
template <class T>
T Abs(T x) {
  return (x < 0 ? -x : x);
}
template <class T>
T safe_sqrt(T x) {
  return sqrt(max(x, (T)0));
}
template <class T, class U, class V>
T addmod(T x, U k, V __base) {
  return ((x + k) % __base + __base) % __base;
}
template <class T, class U, class V>
T submod(T x, U k, V __base) {
  return ((x - k) % __base + __base) % __base;
}
template <class T, class U, class V>
T mul(T x, U y, V __base) {
  return (long long)x * y % __base;
}
const int N = 2e3 + 22;
const int lg = 12;
struct E {
  int w, u, v;
  E() {}
  E(int _w, int _u, int _v) : w(_w), u(_u), v(_v) {}
  bool operator<(const E &other) const { return w < other.w; }
};
vector<E> edge, adj[N];
vector<int> lab;
int d[N][N], dp[N][lg + 2], f[N];
long long dist[N];
int n;
void loadMatrix() {
  scanf("%d", &n);
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++) scanf("%d", &d[i][j]);
}
void preprocess() {
  for (int i = 1; i <= n; i++)
    for (int j = i; j <= n; j++) {
      if (i == j and d[i][i]) puts("NO"), exit(0);
      if (i != j and (d[i][j] != d[j][i] or d[i][j] == 0)) puts("NO"), exit(0);
      edge.push_back(E(d[i][j], i, j));
    }
}
void dfs(int u, int par, int deep) {
  dp[u][0] = par, f[u] = deep;
  for (int i = 0; i < ((int)adj[u].size()); i++) {
    int v = adj[u][i].u;
    int w = adj[u][i].w;
    if (v == par) continue;
    dist[v] = dist[u] + w;
    dfs(v, u, deep + 1);
  }
}
int lca(int u, int v) {
  if (f[u] < f[v]) swap(u, v);
  for (int j = lg; j >= 0; j--)
    if (f[dp[u][j]] >= f[v]) u = dp[u][j];
  if (u == v) return u;
  for (int j = lg; j >= 0; j--)
    if (dp[u][j] - dp[v][j]) u = dp[u][j], v = dp[v][j];
  return dp[u][0];
}
long long dst(int u, int v) { return dist[u] + dist[v] - 2 * dist[lca(u, v)]; }
int findp(int u) { return lab[u] < 0 ? u : findp(lab[u]); }
bool join(int u, int v) {
  u = findp(u), v = findp(v);
  if (u == v) return false;
  if (lab[u] > lab[v]) swap(u, v);
  lab[u] += lab[v], lab[v] = u;
  return true;
}
void addEdge(int u, int v, int w) {
  adj[u].push_back(E(w, v, -1));
  adj[v].push_back(E(w, u, -1));
}
void solve() {
  sort((edge).begin(), (edge).end());
  lab.resize(n + 2, -1);
  int cnt = 0;
  for (__typeof((edge).begin()) it = (edge).begin(); it != (edge).end(); it++) {
    if (cnt == n - 1) break;
    int w = it->w;
    int u = it->u;
    int v = it->v;
    if (!join(u, v)) continue;
    ++cnt, addEdge(u, v, w);
  }
  if (cnt < n - 1) puts("NO"), exit(0);
  dfs(1, 1, 0);
  for (int j = 1; j <= lg; j++)
    for (int i = 1; i <= n; i++) dp[i][j] = dp[dp[i][j - 1]][j - 1];
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++) {
      if (i == j) continue;
      if (dst(i, j) - 1ll * d[i][j]) puts("NO"), exit(0);
    }
  puts("YES");
}
int main(void) {
  loadMatrix();
  preprocess();
  solve();
}
