#include <bits/stdc++.h>
const int MOD = 1e9 + 7;
const int N = 2e3 + 15;
const int INF = (1 << 30) - 1;
const int letter = 130;
using namespace std;
int n;
int dis[N][N], a[N][N];
int father[N];
int vis[N];
struct node {
  int s, e, len;
} tree[N * N];
struct edges {
  int to, len;
};
vector<edges> G[N];
void init() {
  for (int i = 0; i < n; i++) father[i] = i;
  for (int i = 0; i < n; i++) G[i].clear();
}
int Find(int x) {
  if (x == father[x]) return x;
  return father[x] = Find(father[x]);
}
bool cmp(node a, node b) { return a.len < b.len; }
void bfs(int s) {
  for (int i = 0; i < n; i++) vis[i] = 0;
  vis[s] = 1;
  queue<int> q;
  while (!q.empty()) q.pop();
  q.push(s);
  while (!q.empty()) {
    int x = q.front();
    q.pop();
    for (int i = 0; i < G[x].size(); i++) {
      int b = G[x][i].to;
      if (!vis[b]) {
        int c = G[x][i].len;
        vis[b] = 1;
        if (s != b) {
          a[s][b] = a[s][x] + c;
          q.push(b);
        }
      }
    }
  }
}
int main() {
  while (scanf("%d", &n) != EOF) {
    init();
    memset(a, 0, sizeof(a));
    for (int i = 0; i < n; ++i)
      for (int j = 0; j < n; ++j) {
        scanf("%d", &dis[i][j]);
      }
    int flag = 0;
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++) {
        if (i == j) {
          if (dis[i][j] != 0) {
            flag = 1;
            break;
          }
        } else {
          if (dis[i][j] == 0 || dis[i][j] != dis[j][i]) {
            flag = 1;
            break;
          }
        }
      }
    if (flag == 1) {
      puts("NO");
      continue;
    }
    int cnt = 0;
    for (int i = 0; i < n; i++)
      for (int j = i + 1; j < n; j++) {
        if (dis[i][j]) {
          tree[cnt].s = i, tree[cnt].e = j, tree[cnt].len = dis[i][j];
          cnt++;
        }
      }
    sort(tree, tree + cnt, cmp);
    int sum = 0;
    for (int i = 0; i < cnt; i++) {
      int a = tree[i].s, b = tree[i].e;
      int c = tree[i].len;
      int aa = Find(a);
      int bb = Find(b);
      if (aa != bb) {
        father[bb] = aa;
        sum++;
        G[a].push_back((edges){b, c});
        G[b].push_back((edges){a, c});
        if (sum == n - 1) break;
      }
    }
    flag = 0;
    for (int i = 0; i < n; i++) {
      bfs(i);
      for (int j = 0; j < n; j++) {
        if (i != j) {
          if (a[i][j] != dis[i][j]) {
            flag = 1;
            break;
          }
        }
      }
      if (flag) break;
    }
    if (flag)
      puts("NO");
    else
      puts("YES");
  }
  return 0;
}
