#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2010;
const long long INF = 1e16;
void kill() {
  puts("NO");
  exit(0);
}
int N;
long long dist[MAXN][MAXN];
long long dtree[MAXN];
int whoto[MAXN];
bool intree[MAXN];
vector<pair<int, long long> > adj[MAXN];
void updist(int x) {
  intree[x] = true;
  dtree[x] = 0;
  for (int i = 1; i <= N; i++) {
    if (!intree[i] && dtree[i] > dist[x][i]) {
      dtree[i] = dist[x][i];
      whoto[i] = x;
    }
  }
}
void dfs(int x, int p, long long d, int root) {
  if (dist[root][x] != d) {
    kill();
  }
  for (auto t : adj[x]) {
    if (t.first != p) {
      dfs(t.first, x, d + t.second, root);
    }
  }
}
int main() {
  if (fopen("input.txt", "r")) {
    freopen("input.txt", "r", stdin);
  }
  scanf("%d", &N);
  for (int i = 1; i <= N; i++) {
    for (int j = 1; j <= N; j++) {
      scanf("%lld", &dist[i][j]);
      if (bool(dist[i][j]) == (i == j)) {
        kill();
      }
    }
  }
  fill_n(dtree + 1, N, INF);
  fill_n(intree + 1, N, false);
  updist(1);
  int ans = 0;
  for (int i = 1; i < N; i++) {
    int mn = -1;
    for (int j = 1; j <= N; j++) {
      if (!intree[j]) {
        if (mn == -1 || dtree[j] < dtree[mn]) {
          mn = j;
        }
      }
    }
    adj[mn].push_back(make_pair(whoto[mn], dtree[mn]));
    adj[whoto[mn]].push_back(make_pair(mn, dtree[mn]));
    ans += dtree[mn];
    updist(mn);
  }
  for (int i = 1; i <= N; i++) {
    dfs(i, 0, 0, i);
  }
  puts("YES");
}
