#include <bits/stdc++.h>
using namespace std;
const int N = 2e6;
const long long LIM = 1e18;
const int INF = 0x3f3f3f3f;
const double eps = 1e-4;
const double PI = atan(1.0) * 4;
const int mod = 1e9 + 7;
int n, m, d[2005][2005], dist[2005];
int fa[2005];
struct Edge {
  int x, y, w;
  bool friend operator<(Edge e, Edge g) { return (e.w < g.w); }
} edge[N + 10];
vector<Edge> g[2005];
int Find(int x) {
  if (x == fa[x]) return x;
  return fa[x] = Find(fa[x]);
}
void dfs(int x, int pre) {
  for (int i = 0, sz = (int)g[x].size(); i < sz; i++) {
    Edge y = g[x][i];
    if (y.y == pre) continue;
    dist[y.y] = dist[x] + y.w;
    dfs(y.y, x);
  }
}
int main() {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  ;
  cin >> n;
  for (int i = 1; i <= n; i++) fa[i] = i;
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++) {
      cin >> d[i][j];
      if (i == j && d[i][j]) {
        cout << "NO";
        return 0;
      }
      if (i != j && !d[i][j]) {
        cout << "NO";
        return 0;
      }
    }
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++)
      if (d[i][j] != d[j][i]) {
        cout << "NO";
        return 0;
      }
  for (int i = 1; i <= n; i++)
    for (int j = 1; j < i; j++) edge[++m] = (Edge){i, j, d[i][j]};
  sort(edge + 1, edge + m + 1);
  for (int i = 1; i <= m; i++) {
    int x = Find(edge[i].x), y = Find(edge[i].y);
    if (x == y) continue;
    fa[x] = y;
    g[edge[i].x].push_back((Edge){edge[i].x, edge[i].y, edge[i].w});
    g[edge[i].y].push_back((Edge){edge[i].y, edge[i].x, edge[i].w});
  }
  for (int i = 1; i <= n; i++) {
    dist[i] = 0;
    dfs(i, 0);
    for (int j = 1; j <= n; j++)
      if (dist[j] != d[i][j]) {
        cout << "NO";
        return 0;
      }
  }
  cout << "YES";
  return 0;
}
