#include <bits/stdc++.h>
using namespace std;
struct Node {
  int u, v, w;
  bool operator<(const Node &a) const { return w < a.w; }
};
struct Node2 {
  int to, v;
};
vector<Node> adj;
vector<Node2> tr[2010];
int a[2010][2010], tt[2010][2010];
int d[2010][2010], anc[2020][20], l[2010], fa[2010];
void dfs(int x, int fa, int ro, int dis) {
  d[x][ro] = dis;
  d[ro][x] = dis;
  for (int i = 0; i < tr[x].size(); i++) {
    int to = tr[x][i].to;
    int v = tr[x][i].v;
    if (to != fa) {
      dfs(to, x, ro, dis + v);
    }
  }
}
int root(int p) {
  if (fa[p] == p) {
    return p;
  }
  return fa[p] = root(fa[p]);
}
void merge(int x, int y) { fa[root(x)] = root(y); }
int main() {
  int n, flag = 0;
  cin >> n;
  for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= n; j++) {
      scanf("%d", &a[i][j]);
      if (a[i][j] < 0) {
        flag = 1;
      }
      if (i == j && a[i][j] != 0) {
        flag = 1;
      }
      if (i != j && a[i][j] == 0) {
        flag = 1;
      }
      if (j < i && a[i][j] != a[j][i]) {
        flag = 1;
      }
      if (i < j) {
        adj.push_back((Node){i, j, a[i][j]});
      }
    }
  }
  if (flag) {
    cout << "NO";
    return 0;
  }
  sort(adj.begin(), adj.end());
  int cnt = 0;
  for (int i = 1; i <= n; i++) {
    fa[i] = i;
  }
  int tot = 0;
  for (int i = 0; i < adj.size(); i++) {
    int u = adj[i].u;
    int v = adj[i].v;
    int w = adj[i].w;
    if (root(u) != root(v)) {
      tot++;
      merge(u, v);
      tr[u].push_back((Node2){v, w});
      tr[v].push_back((Node2){u, w});
    }
    if (tot == n - 1) break;
  }
  for (int i = 1; i <= n; i++) {
    dfs(i, 0, i, 0);
  }
  for (int i = 0; i < adj.size(); i++) {
    int u = adj[i].u;
    int v = adj[i].v;
    int w = adj[i].w;
    if (w != d[u][v]) {
      cout << "NO";
      return 0;
    }
  }
  cout << "YES";
  return 0;
}
