#include <bits/stdc++.h>
using namespace std;
struct arco {
  int p, a, peso;
  arco() : p(0), a(0), peso(0) {}
  arco(int x, int y, int z) : p(x), a(y), peso(z) {}
};
int N;
int mat[2010][2010];
vector<arco> Edge;
vector<pair<int, int> > colleg[2010];
bool visited[2010];
int cammini[2010][2010];
class UnionFind {
  vector<int> padri, rango;

 public:
  UnionFind(const int x) {
    rango.assign(x + 10, 0);
    padri.resize(x + 10);
    for (int i = 0; i <= x; i++) padri[i] = i;
  }
  int Padre(int x) {
    if (x == padri[x]) return x;
    padri[x] = Padre(padri[x]);
    return padri[x];
  }
  bool Stesso(int a, int b) { return (Padre(a) == Padre(b)); }
  void Unisci(int a, int b) {
    int p1 = Padre(a), p2 = Padre(b);
    if (rango[p1] > rango[p2])
      padri[p2] = p1;
    else if (rango[p1] < rango[p2])
      padri[p1] = p2;
    else {
      rango[p1]++;
      padri[p2] = p1;
    }
  }
};
bool Esatta() {
  for (int i = 0; i < N; i++)
    if (mat[i][i] != 0) return false;
  for (int i = 0; i < N; i++)
    for (int j = 0; j < N; j++) {
      if (i == j) continue;
      if (mat[i][j] <= 0) return false;
      if (mat[i][j] != mat[j][i]) return false;
    }
  return true;
}
void Dfs(int n, int princ) {
  visited[n] = true;
  for (vector<pair<int, int> >::iterator i = colleg[n].begin();
       i != colleg[n].end(); i++) {
    if (!visited[i->first]) {
      cammini[princ][i->first] = i->second + cammini[princ][n];
      Dfs(i->first, princ);
    }
  }
  visited[n] = false;
}
bool Controlla() {
  for (int i = 0; i < N; i++) {
    cammini[i][i] = 0;
    Dfs(i, i);
  }
  for (int i = 0; i < N; i++)
    for (int j = 0; j < N; j++)
      if (cammini[i][j] != mat[i][j]) return false;
  return true;
}
bool cmp(const arco& a, const arco& b) { return (a.peso < b.peso); }
int main() {
  ios::sync_with_stdio(false);
  cin >> N;
  for (int i = 0; i < N; i++)
    for (int j = 0; j < N; j++) cin >> mat[i][j];
  if (!Esatta())
    cout << "NO\n";
  else {
    for (int i = 0; i < N; i++)
      for (int j = i + 1; j < N; j++) Edge.push_back(arco(i, j, mat[i][j]));
    sort(Edge.begin(), Edge.end(), cmp);
    UnionFind insieme(N);
    vector<arco>::iterator i = Edge.begin();
    int c = 0;
    while (c < N - 1) {
      int parti = i->p, arriva = i->a;
      if (!insieme.Stesso(parti, arriva)) {
        insieme.Unisci(parti, arriva);
        colleg[parti].push_back(make_pair(arriva, i->peso));
        colleg[arriva].push_back(make_pair(parti, i->peso));
        c++;
      }
      i++;
    }
    if (Controlla())
      cout << "YES\n";
    else
      cout << "NO\n";
  }
  return 0;
}
