#include <bits/stdc++.h>
using namespace std;
template <typename __ll>
inline void read(__ll &m) {
  __ll x = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  m = x * f;
}
int dis[2001][2001];
struct edge {
  int u, v, w, next;
  bool operator<(const edge &p) const { return w < p.w; }
} d[2001 * 2001], ds[2001 * 2001];
int father[2001];
int head[2001], cnt, c, n;
void add(int u, int v, int w) {
  cnt++;
  d[cnt].u = u;
  d[cnt].v = v;
  d[cnt].w = w;
  d[cnt].next = head[u];
  head[u] = cnt;
}
void adds(int u, int v, int w) {
  c++;
  ds[c].u = u;
  ds[c].v = v;
  ds[c].w = w;
}
int Find(int x) {
  if (father[x] != x) father[x] = Find(father[x]);
  return father[x];
}
void kruskal() {
  int i, u, v, w;
  sort(ds + 1, ds + 1 + c);
  for (i = 1; i <= n; i++) father[i] = i;
  memset(head, -1, sizeof(head));
  cnt = 0;
  for (i = 1; i <= c; i++) {
    u = ds[i].u;
    v = ds[i].v;
    w = ds[i].w;
    int f1 = Find(u);
    int f2 = Find(v);
    if (f1 != f2) {
      father[f2] = f1;
      add(u, v, w);
      add(v, u, w);
    }
  }
}
bool vis[2001];
int dist[2001];
void dfs(int x, int w) {
  vis[x] = 1;
  dist[x] = w;
  int i, v;
  for (i = head[x]; i != -1; i = d[i].next) {
    v = d[i].v;
    if (vis[v]) continue;
    dfs(v, w + d[i].w);
  }
}
int main() {
  int i, j;
  read(n);
  for (i = 1; i <= n; i++)
    for (j = 1; j <= n; j++) read(dis[i][j]);
  if (n == 1 && !dis[1][1]) {
    puts("YES");
    return 0;
  }
  for (i = 1; i <= n; i++)
    if (dis[i][i] != 0) {
      puts("NO");
      return 0;
    }
  for (i = 1; i <= n; i++)
    for (j = i + 1; j <= n; j++) {
      if (dis[i][j] != dis[j][i] || (dis[i][j] == 0)) {
        puts("NO");
        return 0;
      }
      adds(i, j, dis[i][j]);
    }
  kruskal();
  int flag = 0;
  for (i = 1; i <= n; i++) {
    if (flag) break;
    for (j = 1; j <= n; j++) vis[j] = 0;
    dfs(i, 0);
    for (j = 1; j <= n; j++)
      if (!vis[j] || dist[j] != dis[i][j]) {
        flag = 1;
        break;
      }
  }
  puts(flag == 1 ? "NO" : "YES");
}
