#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-7;
const int inf = 0x3f3f3f3f;
const long long linf = 0x3f3f3f3f3f3f3f3fLL;
int mat[2005][2005], n;
int T[2005], P[2005][20], L[2005];
void pre() {
  memset(P, -1, sizeof P);
  for (int i = (0); i < (n); ++i) P[i][0] = T[i];
  for (int j = 1; (1 << j) < n; ++j) {
    for (int i = (0); i < (n); ++i)
      if (~P[i][j - 1]) {
        P[i][j] = P[P[i][j - 1]][j - 1];
      }
  }
}
int LCA(int p, int q) {
  int log;
  if (L[p] < L[q]) swap(p, q);
  for (log = 1; (1 << log) <= L[p]; ++log)
    ;
  --log;
  for (int i = log; i >= 0; --i) {
    if (L[p] - (1 << i) >= L[q]) p = P[p][i];
  }
  if (p == q) return p;
  for (int 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];
}
int to[4005], ant[4005], adj[2005], cost[4005], z = 0;
long long dist[2005];
void add(int a, int b, int c) {
  to[z] = b;
  ant[z] = adj[a];
  cost[z] = c;
  adj[a] = z++;
}
struct Edge {
  int a, b, c;
  Edge() {}
  Edge(int a, int b, int c) : a(a), b(b), c(c) {}
  bool operator<(const Edge &rhs) const { return c < rhs.c; }
} edges[2005 * 2005];
int rep[2005];
int fset(int a) { return a == rep[a] ? a : rep[a] = fset(rep[a]); }
void unir(int a, int b) { rep[fset(a)] = fset(b); }
bool sameSet(int a, int b) { return fset(a) == fset(b); }
int main() {
  scanf("%d", &n);
  for (int i = (0); i < (n); ++i)
    for (int j = (0); j < (n); ++j) scanf("%d", &mat[i][j]);
  priority_queue<int> pq;
  for (int i = (0); i < (n); ++i) {
    rep[i] = i;
    if (mat[i][i] != 0) {
      puts("NO");
      return 0;
    }
    for (int j = (i + 1); j < (n); ++j) {
      if (mat[i][j] != mat[j][i] || mat[i][j] == 0) {
        puts("NO");
        return 0;
      }
    }
  }
  int addei = 0;
  for (int i = (0); i < (n); ++i)
    for (int j = (i + 1); j < (n); ++j) {
      edges[addei++] = Edge(i, j, mat[i][j]);
    }
  sort(edges, edges + addei);
  memset(adj, -1, sizeof adj);
  z = 0;
  for (int i = (0); i < (addei); ++i) {
    int a = edges[i].a, b = edges[i].b, c = edges[i].c;
    if (sameSet(a, b)) continue;
    unir(a, b);
    add(a, b, c);
    add(b, a, c);
  }
  memset(T, -1, sizeof T);
  queue<int> q;
  q.push(0);
  memset(dist, inf, sizeof dist);
  dist[0] = 0;
  T[0] = -1;
  L[0] = 0;
  while (!q.empty()) {
    int f = q.front();
    q.pop();
    for (int i = adj[f]; ~i; i = ant[i]) {
      int v = to[i];
      if (dist[v] == linf) {
        T[v] = f;
        L[v] = L[f] + 1;
        dist[v] = dist[f] + cost[i];
        q.push(v);
      }
    }
  }
  pre();
  for (int i = (0); i < (n); ++i)
    for (int j = (i + 1); j < (n); ++j) {
      int lca = LCA(i, j);
      if (dist[i] + dist[j] - 2 * dist[lca] != mat[i][j]) {
        puts("NO");
        return 0;
      }
    }
  puts("YES");
  return 0;
}
