#include <bits/stdc++.h>
using namespace std;
long long n;
static const long long maxn = 2005;
long long M[maxn][maxn];
long long MyM[maxn][maxn];
vector<vector<long long>*> graph;
long long dsu[maxn];
bool PreCheck() {
  for (long long i = 0; i < n; i++) {
    if (M[i][i] != 0) return false;
  }
  for (long long i = 0; i < n; i++)
    for (long long j = 0; j < n; j++) {
      if (M[i][j] != M[j][i]) return false;
    }
  return true;
}
long long edge_count = 0;
struct edge {
  long long u;
  long long v;
  long long d;
  bool operator<(const edge& rhs) const { return d < rhs.d; }
};
long long dsu_root(long long i) {
  while (dsu[i] != i) {
    dsu[i] = dsu[dsu[i]];
    i = dsu[i];
  }
  return i;
}
bool dsu_connected(long long i, long long j) {
  return dsu_root(i) == dsu_root(j);
}
void dsu_join(long long i, long long j) {
  long long r = rand() % 2;
  if (r)
    dsu[dsu_root(i)] = j;
  else
    dsu[dsu_root(j)] = i;
}
void init() {
  for (long long i = 0; i < n; i++) {
    dsu[i] = i;
    vector<long long>* v = new vector<long long>();
    graph.push_back(v);
  }
}
bool dfs_visited[maxn];
void dfs(long long i, long long root, long long curr) {
  if (dfs_visited[i]) return;
  dfs_visited[i] = true;
  for (auto it : *graph[i]) {
    if (dfs_visited[it])
      continue;
    else {
      long long d = curr + M[i][it];
      MyM[root][it] = d;
      MyM[it][root] = d;
      dfs(it, root, d);
    }
  }
}
bool FinalCheck() {
  for (long long i = 1; i < n; i++) {
    if (!dsu_connected(i, 0)) return false;
  }
  for (long long i = 0; i < n; i++)
    for (long long j = 0; j < i; j++) {
      if (M[i][j] != MyM[i][j]) return false;
    }
  return true;
}
int main() {
  ios_base::sync_with_stdio(0);
  cin >> n;
  init();
  for (long long i = 0; i < n; i++)
    for (long long j = 0; j < n; j++) {
      cin >> M[i][j];
      MyM[i][j] = 0;
    }
  if (!PreCheck()) {
    cout << "NO" << endl;
    return 0;
  }
  vector<edge> edges;
  for (long long i = 0; i < n; i++)
    for (long long j = 0; j < i; j++) {
      edge curr;
      curr.u = i;
      curr.v = j;
      curr.d = M[i][j];
      if (curr.d > 0) edges.push_back(curr);
    }
  sort(edges.begin(), edges.end());
  for (auto it : edges) {
    if (!dsu_connected(it.u, it.v)) {
      edge_count++;
      graph[it.u]->push_back(it.v);
      graph[it.v]->push_back(it.u);
      dsu_join(it.u, it.v);
    }
  }
  if (edge_count != n - 1) {
    cout << "NO" << endl;
    return 0;
  }
  for (long long i = 0; i < n; i++) {
    memset(dfs_visited, 0, sizeof(dfs_visited));
    dfs(i, i, 0);
  }
  if (FinalCheck()) {
    cout << "YES" << endl;
  } else {
    cout << "NO" << endl;
  }
  return 0;
}
