#include <bits/stdc++.h>
using namespace std;
int mat[2011][2011], N;
vector<pair<int, pair<int, int> > > edge_list;
vector<pair<int, int> > adj[2011];
int par[2011];
int findpar(int p) {
  if (par[p] == p)
    return p;
  else
    return par[p] = findpar(par[p]);
}
bool same(int x, int y) { return findpar(x) == findpar(y); }
void join(int x, int y) { par[findpar(x)] = findpar(y); }
int L[2011];
int T[2011];
int P[2011][20];
void preprocess() {
  int i, j;
  for (i = 0; i < N; i++)
    for (j = 0; 1 << j < N; j++) P[i][j] = -1;
  for (i = 0; i < N; i++) P[i][0] = T[i];
  for (j = 1; 1 << j < N; j++)
    for (i = 0; i < N; i++)
      if (P[i][j - 1] != -1) P[i][j] = P[P[i][j - 1]][j - 1];
}
int query(int p, int q) {
  int tmp, log, i;
  if (L[p] < L[q]) tmp = p, p = q, q = tmp;
  for (log = 1; 1 << log <= L[p]; log++)
    ;
  log--;
  for (i = log; i >= 0; i--)
    if (L[p] - (1 << i) >= L[q]) p = P[p][i];
  if (p == q) return p;
  for (i = log; i >= 0; i--)
    if (P[p][i] != -1 && P[p][i] != P[q][i]) {
      p = P[p][i];
      q = P[q][i];
    }
  return T[p];
}
bool vis[2011];
void dfs(int n, int lv) {
  L[n] = lv;
  vis[n] = 1;
  for (int i = 0; i < (int)adj[n].size(); i++) {
    int u = adj[n][i].first;
    if (!vis[u]) {
      T[u] = n;
      dfs(u, lv + 1);
    }
  }
}
int main() {
  int i, j, n;
  scanf("%d", &n);
  N = n;
  bool valid = 1;
  for (i = 0; i < n; i++) {
    for (j = 0; j < n; j++) {
      scanf("%d", &mat[i][j]);
      if (i == j && mat[i][j] != 0) valid = 0;
      if (i != j && mat[i][j] == 0) valid = 0;
    }
  }
  for (i = 0; i <= n - 2 && valid; i++) {
    for (j = i + 1; j <= n - 1 && valid; j++) {
      if (mat[i][j] != mat[j][i]) valid = 0;
      edge_list.push_back(make_pair(mat[i][j], make_pair(i, j)));
    }
  }
  if (!valid) {
    puts("NO");
    return 0;
  }
  sort(edge_list.begin(), edge_list.end());
  for (i = 0; i < n; i++) par[i] = i;
  for (i = 0; i < (int)edge_list.size(); i++) {
    int x = edge_list[i].second.first, y = edge_list[i].second.second;
    if (!same(x, y)) {
      join(x, y);
      adj[x].push_back(make_pair(y, edge_list[i].first));
      adj[y].push_back(make_pair(x, edge_list[i].first));
    }
  }
  memset(vis, 0, sizeof vis);
  T[0] = -1;
  dfs(0, 0);
  preprocess();
  for (i = 1; i <= n - 2 && valid; i++) {
    for (j = i + 1; j <= n - 1 && valid; j++) {
      int a = query(i, j);
      if (mat[i][j] != mat[0][i] + mat[0][j] - 2 * mat[0][a]) {
        valid = 0;
      }
    }
  }
  if (valid)
    puts("YES");
  else
    puts("NO");
  return 0;
}
