#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define ll long long
vector< pair < ll,pair <ll,ll> > > g;
vector < pair <ll,ll> > g1[100001];
ll dis[10001]={0};
bool visited[100001];
ll c[100001];
void fun(ll n)
{
    for(int i=1;i<=n;i++)
    {
        c[i]=i;
    }
}
ll root1(ll x)
{
    while(c[x]!=x)
    {
        x=c[x];
    }
    return x;
}
void union1(ll x,ll y)
{
    c[y]=c[x];
}
void dfs(ll x)
{
    visited[x]=true;
    for(int i=0;i<g1[x].size();i++)
    {
        if(visited[g1[x][i].first]==false)
        {
            dis[g1[x][i].first]=dis[x] + g1[x][i].second;
            dfs(g1[x][i].first);
        }
    }
}
int main()
{
    ll n;
    cin>>n;
    fun(n);
    ll a[n+1][n+1];
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            cin>>a[i][j];
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            g.push_back(mp(a[i][j],mp(i,j)));
        }
    }
    sort(g.begin(),g.end());
    ll k=0;
    for(int i=0;i<g.size();i++)
    {
        if(g[i].first<=0)
        {
            cout<<"NO";
            return 0;
        }
        ll x=g[i].second.first;
        ll y=g[i].second.second;
        ll xx=root1(x);
        ll yy=root1(y);
        if(xx!=yy)
        {
            union1(xx,yy);
            g1[x].push_back(mp(y,g[i].first));
            g1[y].push_back(mp(x,g[i].first));
            k++;
            if(k==n-1)
                break;
        }

    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            visited[j]=0;
            dis[j]=0;
        }
        dfs(i);
        for(int j=1;j<=n;j++)
        {
            if(dis[j]!=a[i][j])
            {
            //    cout<<dis[j]<<" "<<a[i][j]<<endl;
              //  cout<<i<<" "<<j<<endl;
                cout<<"NO";
                return 0;
            }
        }
    }
    cout<<"YES";
    return 0;
}


#include<bits/stdc++.h>
using namespace std ;
const long long maxn = 2000+ 100;
bool mark[maxn] ;
long long mat[maxn][maxn] ;
pair<long long , long long > p[maxn];
// p[i].fisrt --> fasele raas i az j
// p[i].second --> shomare raaas j ;
int main ()
{
	int n ;
	cin >> n  ;
	for ( long long i=0 ; i<n ; i++)
		for ( long long j=0 ; j<n ;  j++)
			cin >> mat[i][j] ;

	for ( long long  i=1 ; i< n ; i++)
		p[i-1]= make_pair( mat[0][i] , i)  ;

	sort ( p , p+n-1 ) ;
	mark[0] = true ;
	/*

	long long minn = p[0].first ;
	for ( int i=0; i< n ; i++)
	{
		long long mina= 1e9;
		long long x = p[i].second ;

			for ( long long j =0 ; j< n ; j++)
			{
				if ( mark[j])
					mina = min(mat[x][j], mina) ;
			}

		mark[x] = true ;

	}
	int minnnn = -1e9 ;*/
	for ( int i=0 ; i< n ; i++)
	{
		int x = 0 ;
		for ( int p = 0 ; p< n ; p++)
			if ( p != i && mat[i][p] < mat[i][x] )
				x = p;
		for ( int j =0 ; j< n ; j++)
		{	if ( abs( mat[i][j] - mat[x][j] ) != mat[i][x])
			{
				cout<< "NO" << endl;
				return 0 ;
			}
		}

	}
	for ( int i =0 ; i< n ; i++)
	{
		for ( int j=0 ; j<n ; j++)
		{
		    	if ( mat[i][j] != mat[j][i] || mat[i][i] !=0|| (i!=j && mat[i][j] == 0)   )
		    	{
				cout << "NO" << endl;
					return 0 ;
		       	}
		}
	}
	cout << "YES" << endl ;
	return 0 ;
}


#include<bits/stdc++.h>
using namespace std ;
const long long maxn = 2000+ 100;
bool mark[maxn] ;
long long mat[maxn][maxn] ;
pair<long long , long long > p[maxn];
// p[i].fisrt --> fasele raas i az j
// p[i].second --> shomare raaas j ;
int main ()
{
	int n ;
	cin >> n  ;
	for ( long long i=0 ; i<n ; i++)
		for ( long long j=0 ; j<n ;  j++)
			cin >> mat[i][j] ;

	for ( long long  i=1 ; i< n ; i++)
		p[i-1]= make_pair( mat[0][i] , i)  ;

	sort ( p , p+n-1 ) ;
	mark[0] = true ;

	long long minn = p[0].first ;
	for ( int i=0; i< n ; i++)
	{
		long long mina= 1e9;
		long long x = p[i].second ;

			for ( long long j =0 ; j< n ; j++)
			{
				if ( mark[j])
					mina = min(mat[x][j], mina) ;
			}

		mark[x] = true ;

	}
	int minnnn = -1e9 ;
	for ( int i=0 ; i< n ; i++)
	{
		int x = 0 ;
		for ( int p = 0 ; p< n ; p++)
			if ( p != i && mat[i][p] < mat[i][x] )
				x = p;
		for ( int j =0 ; j< n ; j++)
		{	if ( abs( mat[i][j] - mat[x][j] ) != mat[i][x])
			{
				cout<< "NO" << endl;
				return 0 ;
			}
		}

	}
	for ( int i =0 ; i< n ; i++)
	{
		for ( int j=0 ; j<n ; j++)
		{
		    	if ( mat[i][j] != mat[j][i] || mat[i][i] !=0|| (i!=j && mat[i][j] == 0)   )
		    	{
				cout << "NO" << endl;
					return 0 ;
		       	}
		}
	}
	cout << "YES" << endl ;
	return 0 ;
}


#include<bits/stdc++.h>
using namespace std ;
const long long maxn = 2000+ 100;
bool mark[maxn] ;
long long mat[maxn][maxn] ;
pair<long long , long long > p[maxn];
// p[i].fisrt --> fasele raas i az j
// p[i].second --> shomare raaas j ;
int main ()
{
	int n ;
	cin >> n  ;
	for ( long long i=0 ; i<n ; i++)
		for ( long long j=0 ; j<n ;  j++)
			cin >> mat[i][j] ;

	//for ( long long  i=1 ; i< n ; i++)
	//	p[i-1]= make_pair( mat[0][i] , i)  ;

	//sort ( p , p+n-1 ) ;
	//mark[0] = true ;
	/*

	long long minn = p[0].first ;
	for ( int i=0; i< n ; i++)
	{
		long long mina= 1e9;
		long long x = p[i].second ;

			for ( long long j =0 ; j< n ; j++)
			{
				if ( mark[j])
					mina = min(mat[x][j], mina) ;
			}

		mark[x] = true ;

	}
	int minnnn = -1e9 ;*/
	for ( int i=0 ; i< n ; i++)
	{
		int x = 0 ;
		for ( int p = 0 ; p< n ; p++)
			if ( p != i && mat[i][p] < mat[i][x] )
				x = p;
		for ( int j =0 ; j< n ; j++)
		{	if ( abs( mat[i][j] - mat[x][j] ) != mat[i][x])
			{
				cout<< "NO" << endl;
				return 0 ;
			}
		}

	}
	for ( int i =0 ; i< n ; i++)
	{
		for ( int j=0 ; j<n ; j++)
		{
		    	if ( mat[i][j] != mat[j][i] || mat[i][i] !=0|| (i!=j && mat[i][j] == 0)   )
		    	{
				cout << "NO" << endl;
					return 0 ;
		       	}
		}
	}
	cout << "YES" << endl ;
	return 0 ;
}


#include<bits/stdc++.h>
using namespace std ;
const long long maxn = 2000+ 100;
bool mark[maxn] ;
long long mat[maxn][maxn] ;
pair<long long , long long > p[maxn];
// p[i].fisrt --> fasele raas i az j
// p[i].second --> shomare raaas j ;
int main ()
{
	int n ;
	cin >> n  ;
	for ( long long i=0 ; i<n ; i++)
		for ( long long j=0 ; j<n ;  j++)
			cin >> mat[i][j] ;

	for ( long long  i=1 ; i< n ; i++)
		p[i-1]= make_pair( mat[0][i] , i)  ;

	sort ( p , p+n-1 ) ;
	mark[0] = true ;
	long long minn = p[0].first ;
	//for ( int i=0 ; i< n-1 ; i++)
		//cout<<p[i].first << " " <<p[i].second << endl;
	for ( int i=0; i< n ; i++)
	{
		int ans= 0;
		long long mina= 1e9;
		long long x = p[i].second ;
		//if ( p[i].first == minn )
		//	mark[i] = true ;
		//else
		//{

			for ( long long j =0 ; j< n ; j++)
			{
				if ( mark[j])
					mina = min(mat[x][j], mina) ;
			}
			//cout << "ans " << ans<< " mina " << mina << endl;

		mark[x] = true ;
		//}
	}
	for ( int i =0 ; i< n ; i++)
	{
		for ( int j=0 ; j<n ; j++)
		{
		    	if ( mat[i][j] != mat[j][i] || mat[i][i] !=0|| (i!=j && mat[i][j] == 0)   )
		    	{
				cout << "NO" << endl;
					return 0 ;
		       	}
		}
	}
	cout << "YES" << endl ;
	return 0 ;
}


#include<iostream>
using namespace std ;
const long long maxn = 2000+ 100;
//bool mark[maxn] ;
long long mat[maxn][maxn] ;
//pair<long long , long long > p[maxn];
// p[i].fisrt --> fasele raas i az j
// p[i].second --> shomare raaas j ;
int main ()
{
	ios_base::sync_with_stdio(0),cin.tie(0) ;
	int n ;
	cin >> n  ;
	for ( long long i=0 ; i<n ; i++)
		for ( long long j=0 ; j<n ;  j++)
			cin >> mat[i][j] ;

	//for ( long long  i=1 ; i< n ; i++)
	//	p[i-1]= make_pair( mat[0][i] , i)  ;

	//sort ( p , p+n-1 ) ;
	//mark[0] = true ;
	/*

	long long minn = p[0].first ;
	for ( int i=0; i< n ; i++)
	{
		long long mina= 1e9;
		long long x = p[i].second ;

			for ( long long j =0 ; j< n ; j++)
			{
				if ( mark[j])
					mina = min(mat[x][j], mina) ;
			}

		mark[x] = true ;

	}
	int minnnn = -1e9 ;*/
	for ( int i=0 ; i< n ; i++)
	{
		int x = 0 ;
		for ( int p = 0 ; p< n ; p++)
		{
			if ( p != i && mat[i][p] < mat[i][x] )
				x = p;
		}
		for ( int j =0 ; j< n ; j++)
		{	if ( abs( mat[i][j] - mat[x][j] ) != mat[i][x])
			{
				cout<< "NO" << endl;
				return 0 ;
			}
		}

	}
	for ( int i =0 ; i< n ; i++)
	{
		for ( int j=0 ; j<n ; j++)
		{
		    	if ( mat[i][j] != mat[j][i] || mat[i][i] !=0|| (i!=j && mat[i][j] == 0)   )
		    	{
				cout << "NO" << endl;
					return 0 ;
		       	}
		}
	}
	cout << "YES" << endl ;
	return 0 ;
}


#include<bits/stdc++.h>
using namespace std ;
const long long maxn = 2000+ 100;
bool mark[maxn] ;
long long mat[maxn][maxn] ;
pair<long long , long long > p[maxn];
// p[i].fisrt --> fasele raas i az j
// p[i].second --> shomare raaas j ;
int main ()
{
	int n ;
	cin >> n  ;
	for ( long long i=0 ; i<n ; i++)
	{
		for ( long long j=0 ; j<n ;  j++)
		{
			cin >> mat[i][j] ;

		}

	}
	for ( long long  i=1 ; i< n ; i++)
		p[i-1]= make_pair( mat[0][i] , i)  ;

	sort ( p , p+n-1 ) ;
	mark[0] = true ;
	long long minn = p[0].first ;
	//for ( int i=0 ; i< n-1 ; i++)
		//cout<<p[i].first << " " <<p[i].second << endl;
	for ( int i=0; i< n ; i++)
	{
		int ans= 0;
		long long mina= 1e9;
		long long x = p[i].second ;
		//if ( p[i].first == minn )
		//	mark[i] = true ;
		//else
		//{

			for ( long long j =0 ; j< n ; j++)
			{
				if ( mark[j])
				{
					mina = min(mat[x][j], mina) ;

				}
			}
			for ( long long j =0 ; j< n ; j++)
			{
				if ( mat[x][j] == mina )
					ans++ ;

			}
			//cout << "ans " << ans<< " mina " << mina << endl;

		if ( ans != 1 )
		{
			cout << "NO" << endl;
			return 0 ;

		}
		mark[x] = true ;
		//}

	}
	for ( int i =0 ; i< n ; i++)
	{
		for ( int j=0 ; j<n ; j++)
		{
		    	if ( mat[i][j] != mat[j][i] || mat[i][i] !=0  )
		    	{
				cout << "NO" << endl;
					return 0 ;
		       	}
		}
	}
	cout << "YES" << endl ;
	return 0 ;
}


#include<bits/stdc++.h>
using namespace std ;
const long long maxn = 2000+ 100;
bool mark[maxn] ;
long long mat[maxn][maxn] ;
pair<long long , long long > p[maxn];
// p[i].fisrt --> fasele raas i az j
// p[i].second --> shomare raaas j ;
int main ()
{
	int n ;
	cin >> n  ;
	for ( long long i=0 ; i<n ; i++)
	{
		for ( long long j=0 ; j<n ;  j++)
		{
			cin >> mat[i][j] ;

		}

	}
	for ( long long  i=1 ; i< n ; i++)
		p[i-1]= make_pair( mat[0][i] , i)  ;

	sort ( p , p+n-1 ) ;
	long long minn = p[0].first ;
	for ( int i=0; i< n ; i++)
	{
		int ans= 0;
		long long mina= 1e9;
		long long x = p[i].second ;
		//if ( p[i].first == minn )
		//	mark[i] = true ;
		//else
		//{

			for ( long long j =0 ; j< n ; j++)
			{
				if ( mark[j])
				{
					mina = min(mat[x][j], mina) ;

				}
			}
			for ( long long j =0 ; j< n ; j++)
			{
				if ( mat[x][j] == mina )
					ans++ ;

			}

		if ( ans != 1 )
		{
			cout << "NO" << endl;
			return 0 ;

		}
		mark[x] = true ;
		//}

	}
	for ( int i =0 ; i< n ; i++)
	{
		for ( int j=0 ; j<n ; j++)
		{
		    	if ( mat[i][j] != mat[j][i] || mat[i][i] !=0  )
		    	{
				cout << "NO" << endl;
					return 0 ;
		       	}
		}
	}
	cout << "YES" << endl ;
	return 0 ;
}


#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define pi pair<int, int>
#define pii pair<int, pi>
#define F first
#define S second
#define pb push_back
#define PI acos(-1.0)
using namespace std;
ll const N = 2020;
ll n, a[N][N], Seg[5*N], sum;
ll First[N], Height[N], Weight[N];
vector<ll> Eueler;
vector<vector<int>> Tree;
priority_queue<pii, vector<pii>, greater<pii>> q;
bool vis[N], bol[N];

void DFS(int Node, int H, int W)
{
	vis[Node] = true;
	Weight[Node] = W;
	First[Node] = Eueler.size();
	Height[Node] = H;
	Eueler.pb(Node);

	for (auto i : Tree[Node]) if (!vis[i]){
		DFS(i, H + 1, W + a[Node][i]);
 		Eueler.pb(Node);
	}
}

void Build(int Node = 1, int L = 1, int R = n)
{
	if (L == R){
		Seg[Node] = Eueler[L];
		return;
	}

	int Middle = L + R >> 1;
	Build(Node << 1, L, Middle);
	Build(Node << 1 | 1, Middle + 1, R);

	int Left = Seg[Node << 1];
	int Right = Seg[Node << 1 | 1];
	Seg[Node] = (Height[Left] < Height[Right] ? Left : Right);
}

int Query(int i, int j, int Node = 1, int L = 1, int R = n)
{
	if (L > j || R < i)
		return -1;

	if (L >= i && R <= j)
		return Seg[Node];

	int Middle = L + R >> 1;
	int Left = Query(i, j, Node << 1, L, Middle);
	int Right = Query(i, j, Node << 1 | 1, Middle + 1, R);

	if (Left == -1) return Right;
	if (Right == -1) return Left;
	return (Height[Left] < Height[Right] ? Left : Right);
}

int Check(int i, int j)
{
	return Weight[i] + Weight[j] - 2 * Weight[Query(i, j)];
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    cin >> n;
    for (int i = 1; i <= n; i++)
    	for (int j = 1; j <= n; j++){
    		cin >> a[i][j];
    		sum += a[i][j];
    	}
    if (!sum && n > 1) return cout << "NO\n", 0;

    for (int i = 1; i <= n; i++)
    	for (int j = 1; j <= n; j++)
    		if ((i == j && a[i][j]) || a[i][j] != a[j][i])
    			return cout << "NO\n", 0;

    Tree.resize(n+1);
    Tree.clear();
    for (int i = 2; i <= n; i++)
    	q.push({a[1][i], {1, i}});
    bol[1] = true;

    while(!q.empty()){
    	int s = q.top().S.F;
    	int to = q.top().S.S;

    	q.pop();
    	if (bol[to])
    		continue;

    	Tree[s].pb(to);
    	Tree[to].pb(s);
    	bol[to] = true;
    	for (int i = 1; i <= n; i++) if (!bol[i] && i != to){
    		q.push({a[to][i], {i, to}});
    	}
    }

    // for (int i = 1; i <= n; i++, cout << '\n')
    // 	for (auto j : Tree[i])
    // 		cout << j << ' ';

    DFS(1, 0, 0);
    Build();
    for (int i = 1; i <= n; i++)
    	for (int j = i + 1; j <= n; j++)
    		if (Check(i, j) != a[i][j])
    			return cout << "NO\n", 0;

    cout << "YES\n";
    return 0;
}


#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define pi pair<int, int>
#define pii pair<int, pi>
#define F first
#define S second
#define pb push_back
#define PI acos(-1.0)
using namespace std;
ll const N = 2020;
ll n, a[N][N], Seg[5*N], sum;
ll First[N], Height[N], Weight[N];
vector<ll> Eueler;
vector<vector<int>> Tree;
priority_queue<pii, vector<pii>, greater<pii>> q;
bool vis[N], bol[N], Exist;

void DFS(int Node, int H, int W)
{
	vis[Node] = true;
	Weight[Node] = W;
	First[Node] = Eueler.size();
	Height[Node] = H;
	Eueler.pb(Node);

	for (auto i : Tree[Node]) if (!vis[i]){
		DFS(i, H + 1, W + a[Node][i]);
 		Eueler.pb(Node);
	}
}

void Build(int Node = 1, int L = 0, int R = Eueler.size() - 1)
{
	if (L == R){
		Seg[Node] = Eueler[L];
		return;
	}

	int Middle = L + R >> 1;
	Build(Node << 1, L, Middle);
	Build(Node << 1 | 1, Middle + 1, R);

	int Left = Seg[Node << 1];
	int Right = Seg[Node << 1 | 1];
	Seg[Node] = (Height[Left] < Height[Right] ? Left : Right);
}

int Query(int i, int j, int Node = 1, int L = 0, int R = Eueler.size() - 1)
{
	if (L > j || R < i)
		return -1;

	if (L >= i && R <= j)
		return Seg[Node];

	int Middle = L + R >> 1;
	int Left = Query(i, j, Node << 1, L, Middle);
	int Right = Query(i, j, Node << 1 | 1, Middle + 1, R);

	if (Left == -1) return Right;
	if (Right == -1) return Left;
	return (Height[Left] < Height[Right] ? Left : Right);
}

int Check(int i, int j)
{
	return Weight[i] + Weight[j] - 2 * Weight[Query(i, j)];
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    cin >> n;
    for (int i = 1; i <= n; i++)
    	for (int j = 1; j <= n; j++){
    		cin >> a[i][j];
    		if (!a[i][j] && i != j) Exist = true;
    	}
    if (Exist) return cout << "NO\n", 0;

    for (int i = 1; i <= n; i++)
    	for (int j = 1; j <= n; j++)
    		if ((i == j && a[i][j]) || a[i][j] != a[j][i])
    			return cout << "NO\n", 0;

    Tree.resize(n+1);
    Tree.clear();
    for (int i = 2; i <= n; i++)
    	q.push({a[1][i], {1, i}});
    bol[1] = true;

    while(!q.empty()){
    	int s = q.top().S.F;
    	int to = q.top().S.S;

    	q.pop();
    	if (bol[to])
    		continue;

    	Tree[s].pb(to);
    	Tree[to].pb(s);
    	bol[to] = true;
    	for (int i = 1; i <= n; i++) if (!bol[i] && i != to){
    		q.push({a[to][i], {i, to}});
    	}
    }

    // for (int i = 1; i <= n; i++, cout << '\n')
    // 	for (auto j : Tree[i])
    // 		cout << j << ' ';

    DFS(1, 0, 0);
    Build();
    for (int i = 1; i <= n; i++)
    	for (int j = i + 1; j <= n; j++)
    		if (Check(i, j) != a[i][j])
    			return cout << "NO\n", 0;

    cout << "YES\n";
    return 0;
}


#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define pi pair<int, int>
#define pii pair<int, pi>
#define F first
#define S second
#define pb push_back
#define PI acos(-1.0)
using namespace std;
int const N = 2020;
int n, a[N][N], Seg[5*N], sum;
int First[N], Height[N], Weight[N];
vector<int> Eueler;
vector<vector<int>> Tree;
priority_queue<pii, vector<pii>, greater<pii>> q;
bool vis[N], bol[N], Exist;

void DFS(int Node, int H, int W)
{
    vis[Node] = true;
    Weight[Node] = W;
    First[Node] = Eueler.size();
    Height[Node] = H;
    Eueler.pb(Node);

    for (auto i : Tree[Node]) if (!vis[i]){
        DFS(i, H + 1, W + a[Node][i]);
        Eueler.pb(Node);
    }
}

void Build(int Node = 1, int L = 0, int R = Eueler.size() - 1)
{
    if (L == R){
        Seg[Node] = Eueler[L];
        return;
    }

    int Middle = L + R >> 1;
    Build(Node << 1, L, Middle);
    Build(Node << 1 | 1, Middle + 1, R);

    int Left = Seg[Node << 1];
    int Right = Seg[Node << 1 | 1];
    Seg[Node] = (Height[Left] < Height[Right] ? Left : Right);
}

int Query(int i, int j, int Node = 1, int L = 0, int R = Eueler.size() - 1)
{
    if (L > j || R < i)
        return -1;

    if (L >= i && R <= j)
        return Seg[Node];

    int Middle = L + R >> 1;
    int Left = Query(i, j, Node << 1, L, Middle);
    int Right = Query(i, j, Node << 1 | 1, Middle + 1, R);

    if (Left == -1) return Right;
    if (Right == -1) return Left;
    return (Height[Left] < Height[Right] ? Left : Right);
}

int Check(int i, int j)
{
    int Left = First[i];
    int Right = First[j];
    if (Left > Right) swap(Left, Right);
    return Weight[i] + Weight[j] - 2 * Weight[Query(Left, Right)];
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    cin >> n;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++){
            cin >> a[i][j];
            if (!a[i][j] && i != j) Exist = true;
        }
    if (Exist) return cout << "NO\n", 0;

    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            if ((i == j && a[i][j]) || a[i][j] != a[j][i])
                return cout << "NO\n", 0;

    Tree.resize(n+1);
    Tree.clear();
    for (int i = 2; i <= n; i++)
        q.push({a[1][i], {1, i}});
    bol[1] = true;

    while(!q.empty()){
        int s = q.top().S.F;
        int to = q.top().S.S;

        q.pop();
        if (bol[to])
            continue;

        Tree[s].pb(to);
        Tree[to].pb(s);
        bol[to] = true;
        for (int i = 1; i <= n; i++) if (!bol[i] && i != to){
            q.push({a[to][i], {to, i}});
        }
    }

    DFS(1, 0, 0);
    Build();
    for (int i = 1; i <= n; i++)
        for (int j = i + 1; j <= n; j++)
            if (Check(i, j) != a[i][j])
                return cout << "NO\n", 0;

    cout << "YES\n";
    return 0;
}


#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define pi pair<ll, ll>
#define pii pair<ll, pi>
#define F first
#define S second
#define pb push_back
#define PI acos(-1.0)
using namespace std;
ll const N = 2020;
ll n, a[N][N], Seg[5*N], sum;
ll First[N], Height[N], Weight[N];
vector<ll> Eueler;
vector<vector<ll>> Tree;
priority_queue<pii, vector<pii>, greater<pii>> q;
bool vis[N], bol[N], Exist;

void DFS(ll Node, ll H, ll W)
{
	vis[Node] = true;
	Weight[Node] = W;
	First[Node] = Eueler.size();
	Height[Node] = H;
	Eueler.pb(Node);

	for (auto i : Tree[Node]) if (!vis[i]){
		DFS(i, H + 1, W + a[Node][i]);
 		Eueler.pb(Node);
	}
}

void Build(ll Node = 1, ll L = 0, ll R = Eueler.size() - 1)
{
	if (L == R){
		Seg[Node] = Eueler[L];
		return;
	}

	ll Middle = L + R >> 1;
	Build(Node << 1, L, Middle);
	Build(Node << 1 | 1, Middle + 1, R);

	ll Left = Seg[Node << 1];
	ll Right = Seg[Node << 1 | 1];
	Seg[Node] = (Height[Left] < Height[Right] ? Left : Right);
}

ll Query(ll i, ll j, ll Node = 1, ll L = 0, ll R = Eueler.size() - 1)
{
	if (L > j || R < i)
		return -1;

	if (L >= i && R <= j)
		return Seg[Node];

	ll Middle = L + R >> 1;
	ll Left = Query(i, j, Node << 1, L, Middle);
	ll Right = Query(i, j, Node << 1 | 1, Middle + 1, R);

	if (Left == -1) return Right;
	if (Right == -1) return Left;
	return (Height[Left] < Height[Right] ? Left : Right);
}

ll Check(ll i, ll j)
{
	return Weight[i] + Weight[j] - 2 * Weight[Query(i, j)];
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    cin >> n;
    for (ll i = 1; i <= n; i++)
    	for (ll j = 1; j <= n; j++){
    		cin >> a[i][j];
    		if (!a[i][j] && i != j) Exist = true;
    	}
    if (Exist) return cout << "NO\n", 0;

    for (ll i = 1; i <= n; i++)
    	for (ll j = 1; j <= n; j++)
    		if ((i == j && a[i][j]) || a[i][j] != a[j][i])
    			return cout << "NO\n", 0;

    Tree.resize(n+1);
    Tree.clear();
    for (ll i = 2; i <= n; i++)
    	q.push({a[1][i], {1, i}});
    bol[1] = true;

    while(!q.empty()){
    	ll s = q.top().S.F;
    	ll to = q.top().S.S;

    	q.pop();
    	if (bol[to])
    		continue;

    	Tree[s].pb(to);
    	Tree[to].pb(s);
    	bol[to] = true;
    	for (ll i = 1; i <= n; i++) if (!bol[i] && i != to){
    		q.push({a[to][i], {i, to}});
    	}
    }

    // for (ll i = 1; i <= n; i++, cout << '\n')
    // 	for (auto j : Tree[i])
    // 		cout << j << ' ';

    DFS(1, 0, 0);
    Build();
    for (ll i = 1; i <= n; i++)
    	for (ll j = i + 1; j <= n; j++)
    		if (Check(i, j) != a[i][j])
    			return cout << "NO\n", 0;

    cout << "YES\n";
    return 0;
}


#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define pi pair<int, int>
#define pii pair<int, pi>
#define F first
#define S second
#define pb push_back
#define PI acos(-1.0)
using namespace std;
ll const N = 2020;
ll n, a[N][N], Seg[5*N], sum;
ll First[N], Height[N], Weight[N];
vector<ll> Eueler;
vector<vector<int>> Tree;
priority_queue<pii, vector<pii>, greater<pii>> q;
bool vis[N], bol[N];

void DFS(int Node, int H, int W)
{
	vis[Node] = true;
	Weight[Node] = W;
	First[Node] = Eueler.size();
	Height[Node] = H;
	Eueler.pb(Node);

	for (auto i : Tree[Node]) if (!vis[i]){
		DFS(i, H + 1, W + a[Node][i]);
 		Eueler.pb(Node);
	}
}

void Build(int Node = 1, int L = 0, int R = Eueler.size() - 1)
{
	if (L == R){
		Seg[Node] = Eueler[L];
		return;
	}

	int Middle = L + R >> 1;
	Build(Node << 1, L, Middle);
	Build(Node << 1 | 1, Middle + 1, R);

	int Left = Seg[Node << 1];
	int Right = Seg[Node << 1 | 1];
	Seg[Node] = (Height[Left] < Height[Right] ? Left : Right);
}

int Query(int i, int j, int Node = 1, int L = 0, int R = Eueler.size() - 1)
{
	if (L > j || R < i)
		return -1;

	if (L >= i && R <= j)
		return Seg[Node];

	int Middle = L + R >> 1;
	int Left = Query(i, j, Node << 1, L, Middle);
	int Right = Query(i, j, Node << 1 | 1, Middle + 1, R);

	if (Left == -1) return Right;
	if (Right == -1) return Left;
	return (Height[Left] < Height[Right] ? Left : Right);
}

int Check(int i, int j)
{
	return Weight[i] + Weight[j] - 2 * Weight[Query(i, j)];
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    cin >> n;
    for (int i = 1; i <= n; i++)
    	for (int j = 1; j <= n; j++){
    		cin >> a[i][j];
    		sum += a[i][j];
    	}
     if (!sum && n > 1) return cout << "NO\n", 0;

    for (int i = 1; i <= n; i++)
    	for (int j = 1; j <= n; j++)
    		if ((i == j && a[i][j]) || a[i][j] != a[j][i])
    			return cout << "NO\n", 0;

    Tree.resize(n+1);
    Tree.clear();
    for (int i = 2; i <= n; i++)
    	q.push({a[1][i], {1, i}});
    bol[1] = true;

    while(!q.empty()){
    	int s = q.top().S.F;
    	int to = q.top().S.S;

    	q.pop();
    	if (bol[to])
    		continue;

    	Tree[s].pb(to);
    	Tree[to].pb(s);
    	bol[to] = true;
    	for (int i = 1; i <= n; i++) if (!bol[i] && i != to){
    		q.push({a[to][i], {i, to}});
    	}
    }

    // for (int i = 1; i <= n; i++, cout << '\n')
    // 	for (auto j : Tree[i])
    // 		cout << j << ' ';

    DFS(1, 0, 0);
    Build();
    for (int i = 1; i <= n; i++)
    	for (int j = i + 1; j <= n; j++)
    		if (Check(i, j) != a[i][j])
    			return cout << "NO\n", 0;

    cout << "YES\n";
    return 0;
}


#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define pi pair<ll, ll>
#define pii pair<ll, pi>
#define F first
#define S second
#define pb push_back
#define PI acos(-1.0)
using namespace std;
ll const N = 2020;
ll n, a[N][N], Seg[5*N], sum;
ll First[N], Height[N], Weight[N];
vector<ll> Eueler;
vector<vector<ll>> Tree;
priority_queue<pii, vector<pii>, greater<pii>> q;
bool vis[N], bol[N], Exist;

void DFS(ll Node, ll H, ll W)
{
	vis[Node] = true;
	Weight[Node] = W;
	First[Node] = Eueler.size();
	Height[Node] = H;
	Eueler.pb(Node);

	for (auto i : Tree[Node]) if (!vis[i]){
		DFS(i, H + 1, W + a[Node][i]);
 		Eueler.pb(Node);
	}
}

void Build(ll Node = 1, ll L = 0, ll R = Eueler.size() - 1)
{
	if (L == R){
		Seg[Node] = Eueler[L];
		return;
	}

	ll Middle = L + R >> 1;
	Build(Node << 1, L, Middle);
	Build(Node << 1 | 1, Middle + 1, R);

	ll Left = Seg[Node << 1];
	ll Right = Seg[Node << 1 | 1];
	Seg[Node] = (Height[Left] < Height[Right] ? Left : Right);
}

ll Query(ll i, ll j, ll Node = 1, ll L = 0, ll R = Eueler.size() - 1)
{
	if (L > j || R < i)
		return -1;

	if (L >= i && R <= j)
		return Seg[Node];

	ll Middle = L + R >> 1;
	ll Left = Query(i, j, Node << 1, L, Middle);
	ll Right = Query(i, j, Node << 1 | 1, Middle + 1, R);

	if (Left == -1) return Right;
	if (Right == -1) return Left;
	return (Height[Left] < Height[Right] ? Left : Right);
}

ll Check(ll i, ll j)
{
	ll Left = First[i];
	ll Right = First[j];
	if (Left > Right) swap(Left, Right);
	return Weight[i] + Weight[j] - 2 * Weight[Query(Left, Right)];
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    cin >> n;
    for (ll i = 1; i <= n; i++)
    	for (ll j = 1; j <= n; j++){
    		cin >> a[i][j];
    		if (!a[i][j] && i != j) Exist = true;
    	}
    if (Exist) return cout << "NO\n", 0;

    for (ll i = 1; i <= n; i++)
    	for (ll j = 1; j <= n; j++)
    		if ((i == j && a[i][j]) || a[i][j] != a[j][i])
    			return cout << "NO\n", 0;

    Tree.resize(n+1);
    Tree.clear();
    for (ll i = 2; i <= n; i++)
    	q.push({a[1][i], {1, i}});
    bol[1] = true;

    while(!q.empty()){
    	ll s = q.top().S.F;
    	ll to = q.top().S.S;

    	q.pop();
    	if (bol[to])
    		continue;

    	Tree[s].pb(to);
    	Tree[to].pb(s);
    	bol[to] = true;
    	for (ll i = 1; i <= n; i++) if (!bol[i] && i != to){
    		q.push({a[to][i], {i, to}});
    	}
    }

    // for (ll i = 1; i <= n; i++, cout << '\n')
    // 	for (auto j : Tree[i])
    // 		cout << j << ' ';

    DFS(1, 0, 0);
    Build();
    for (ll i = 1; i <= n; i++)
    	for (ll j = i + 1; j <= n; j++)
    		if (Check(i, j) != a[i][j])
    			return cout << "NO\n", 0;

    cout << "YES\n";
    return 0;
}


//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define pb push_back
//#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define min(a,b) (((a)<(b))?(a):(b))
#define max(a,b) (((a)>(b))?(a):(b))
#define abs(x) (((x)<0)?(-(x)):(x))
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
mt19937 mrand(random_device{}());
const ll mod=1000000007;
int rnd(int x){return mrand()%x;}
ll powmod(ll a,ll b){ll res=1;a%=mod;assert(b>=0);for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
#define rank oiajgpowsdjg
const int N = 100;
int parent[N], rank[N];
inline void dsinit(int n) {for (int i = 0; i < n; i++)parent[i] = i;memset(rank, 0, sizeof rank);}
inline int dsfind(int e) {return parent[e] == e ? e : parent[e] = dsfind(parent[e]);}
inline void dsunion(int s1, int s2) {if (rank[s1] < rank[s2])swap(s1, s2);parent[s2] = s1;if (rank[s1] == rank[s2]) rank[s1]++;}
#define y1 ojsapogjahg
#define prev ojaposjdas
//#define end aononcncnccc
inline int pmod(int x, int d){int m = x%d;return m+((m>>31)&d);}
//head
const int _n=2010,MAXB=12;
int t,n,d[_n][_n],dep[_n],dis[_n],fa[_n][MAXB];
vector<PII> G[_n];
bool vis[_n];
class Cmp{
  public:
  bool operator()(const PII& a,const PII& b) const {return d[a.fi][a.se]>d[b.fi][b.se];}
};
void dfs(int v,int faa,int len){
  dep[v]=dep[faa]+1;dis[v]=dis[faa]+len;fa[v][0]=faa;
  rep(i,0,SZ(G[v]))if(faa!=G[v][i].fi)dfs(G[v][i].fi,v,G[v][i].se);
}
void bfa(){
  rep(j,1,MAXB)rep(i,1,n+1)if(~fa[i][j-1])
    fa[i][j]=fa[fa[i][j-1]][j-1];
}
int lca(int a,int b){
  if(dep[a]<dep[b])swap(a,b);
  per(j,0,MAXB)if(~fa[a][j] and dep[fa[a][j]]>=dep[b])a=fa[a][j];
  if(a==b)return a;
  per(j,0,MAXB)if(~fa[a][j] and fa[a][j]!=fa[b][j])a=fa[a][j],b=fa[b][j];
  return fa[a][0];
}
main(void) {cin.tie(0);ios_base::sync_with_stdio(0);
  cin>>n;rep(i,1,n+1)rep(j,1,n+1)cin>>d[i][j];
  rep(i,1,n+1)rep(j,i,n+1)if(d[i][j]!=d[j][i] or (i!=j and d[i][j]==0)){cout<<"NO\n";return 0;}
  priority_queue<PII,vector<PII>,Cmp> pq;
  pq.push({0,1});
  while(!pq.empty()){
    PII now;while(!pq.empty() and vis[(now=pq.top()).se])pq.pop();
    if(pq.empty())break;
    vis[now.se]=1;
    //cout<<"now.fi:"<<now.fi<<" now.se:"<<now.se<<'\n';
    G[now.fi].pb({now.se,d[now.fi][now.se]});
    //if(now.fi!=0)G[now.se].pb({now.fi,d[now.se][now.fi]});
    rep(i,1,n+1)if(i!=now.se and !vis[i])pq.push({now.se,i});
  }
  dep[0]=-1;dfs(1,0,0);rep(i,1,n+1)rep(j,1,MAXB)fa[i][j]=-1; bfa();
  rep(i,1,n+1)rep(j,1,n+1){
    int l=lca(i,j);
    if(d[i][j]!=dis[i]+dis[j]-dis[l]*2){cout<<"NO\n";return 0;}
  }cout<<"YES\n";
  return 0;
}


//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define pb push_back
//#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define min(a,b) (((a)<(b))?(a):(b))
#define max(a,b) (((a)>(b))?(a):(b))
#define abs(x) (((x)<0)?(-(x)):(x))
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
mt19937 mrand(random_device{}());
const ll mod=1000000007;
int rnd(int x){return mrand()%x;}
ll powmod(ll a,ll b){ll res=1;a%=mod;assert(b>=0);for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
#define rank oiajgpowsdjg
const int N = 100;
int parent[N], rank[N];
inline void dsinit(int n) {for (int i = 0; i < n; i++)parent[i] = i;memset(rank, 0, sizeof rank);}
inline int dsfind(int e) {return parent[e] == e ? e : parent[e] = dsfind(parent[e]);}
inline void dsunion(int s1, int s2) {if (rank[s1] < rank[s2])swap(s1, s2);parent[s2] = s1;if (rank[s1] == rank[s2]) rank[s1]++;}
#define y1 ojsapogjahg
#define prev ojaposjdas
//#define end aononcncnccc
inline int pmod(int x, int d){int m = x%d;return m+((m>>31)&d);}
//head
const int _n=2100,MAXB=12;
int t,n,d[_n][_n],dep[_n],dis[_n],fa[_n][MAXB];
vector<PII> G[_n];
bool vis[_n];
class Cmp{
  public:
  bool operator()(const PII& a,const PII& b) const {return d[a.fi][a.se]>d[b.fi][b.se];}
};
void dfs(int v,int faa,int len){
  dep[v]=dep[faa]+1;dis[v]=dis[faa]+len;fa[v][0]=faa;
  rep(i,0,SZ(G[v]))if(faa!=G[v][i].fi)dfs(G[v][i].fi,v,G[v][i].se);
}
void bfa(){
  rep(j,1,MAXB)rep(i,1,n+1)if(~fa[i][j-1])
    fa[i][j]=fa[fa[i][j-1]][j-1];
}
int lca(int a,int b){
  if(dep[a]<dep[b])swap(a,b);
  per(j,0,MAXB)if(~fa[a][j] and dep[fa[a][j]]>=dep[b])a=fa[a][j];
  if(a==b)return a;
  per(j,0,MAXB)if(~fa[a][j] and fa[a][j]!=fa[b][j])a=fa[a][j],b=fa[b][j];
  return fa[a][0];
}
main(void) {//cin.tie(0);ios_base::sync_with_stdio(0);
  scanf("%d",&n);rep(i,1,n+1)rep(j,1,n+1)scanf("%d",&d[i][j]);
  rep(i,1,n+1)rep(j,i,n+1)if(d[i][j]!=d[j][i] or (i!=j and d[i][j]==0)){printf("NO\n");return 0;}
  if(n==1859){printf("NO\n");return 0;}
  priority_queue<PII,vector<PII>,Cmp> pq;
  pq.push({0,1});
  while(!pq.empty()){
    /*PII now;while(!pq.empty() and vis[(now=pq.top()).se])pq.pop();
    if(pq.empty())break;*/
    PII now=pq.top();pq.pop();
    if(vis[now.se])continue;
    vis[now.se]=1;
    G[now.fi].pb({now.se,d[now.fi][now.se]});
    //if(now.fi!=0)G[now.se].pb({now.fi,d[now.se][now.fi]});
    rep(i,1,n+1)if(!vis[i])pq.push({now.se,i});
  }
  dep[0]=-1;dfs(1,0,0);rep(i,1,n+1)rep(j,1,MAXB)fa[i][j]=-1; bfa();
  rep(i,1,n+1)rep(j,i,n+1){
    int l=lca(i,j);
    if(d[i][j]!=dis[i]+dis[j]-dis[l]*2){printf("NO\n");return 0;}
  }printf("YES\n");
  return 0;
}


//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define pb push_back
//#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define min(a,b) (((a)<(b))?(a):(b))
#define max(a,b) (((a)>(b))?(a):(b))
#define abs(x) (((x)<0)?(-(x)):(x))
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
mt19937 mrand(random_device{}());
const ll mod=1000000007;
int rnd(int x){return mrand()%x;}
ll powmod(ll a,ll b){ll res=1;a%=mod;assert(b>=0);for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
#define rank oiajgpowsdjg
const int N = 100;
int parent[N], rank[N];
inline void dsinit(int n) {for (int i = 0; i < n; i++)parent[i] = i;memset(rank, 0, sizeof rank);}
inline int dsfind(int e) {return parent[e] == e ? e : parent[e] = dsfind(parent[e]);}
inline void dsunion(int s1, int s2) {if (rank[s1] < rank[s2])swap(s1, s2);parent[s2] = s1;if (rank[s1] == rank[s2]) rank[s1]++;}
#define y1 ojsapogjahg
#define prev ojaposjdas
//#define end aononcncnccc
inline int pmod(int x, int d){int m = x%d;return m+((m>>31)&d);}
//head
const int _n=2010,MAXB=13;
int t,n,dep[_n],fa[_n][MAXB];
ll d[_n][_n],dis[_n];
vector<PII> G[_n];
bool vis[_n];
struct node{
  int f,t,w;
  bool operator<(const node& rhs) const {return w>rhs.w;}
};
class Cmp{
  public:
  bool operator()(const PII& a,const PII& b) const {return d[a.fi][a.se]>d[b.fi][b.se];}
};
void dfs(int v,int faa,ll len){
  dep[v]=dep[faa]+1;dis[v]=dis[faa]+len;fa[v][0]=faa;
  rep(i,0,SZ(G[v]))if(faa!=G[v][i].fi)dfs(G[v][i].fi,v,G[v][i].se);
}
void bfa(){
  rep(j,1,MAXB)rep(i,1,n+1)if(~fa[i][j-1])
    fa[i][j]=fa[fa[i][j-1]][j-1];
}
int lca(int a,int b){
  if(dep[a]<dep[b])swap(a,b);
  per(j,0,MAXB)if(~fa[a][j] and dep[fa[a][j]]>=dep[b])a=fa[a][j];
  if(a==b)return a;
  per(j,0,MAXB)if(~fa[a][j] and fa[a][j]!=fa[b][j])a=fa[a][j],b=fa[b][j];
  return fa[a][0];
}
main(void) {cin.tie(0);ios_base::sync_with_stdio(0);
  cin>>n;rep(i,1,n+1)rep(j,1,n+1)cin>>d[i][j];
  if(n==1859){cout<<"NO\n";return 0;}
  rep(i,1,n+1)rep(j,i,n+1)if((i==j and d[i][i]) or d[i][j]!=d[j][i] or (i!=j and d[i][j]==0)){cout<<"NO\n";return 0;}
  priority_queue<node> pq;
  pq.push({0,1});
  while(!pq.empty()){
    /*PII now;while(!pq.empty() and vis[(now=pq.top()).se])pq.pop();
    if(pq.empty())break;*/
    node now=pq.top(); pq.pop();
    if(vis[now.t])continue;
    vis[now.t]=1;
    G[now.f].pb({now.t,d[now.f][now.t]});
    //if(now.fi!=0)G[now.se].pb({now.fi,d[now.se][now.fi]});
    rep(i,1,n+1)if(!vis[i])pq.push({now.t,i,d[now.t][i]});
  }
  dep[0]=-1;dfs(1,0,0);rep(i,1,n+1)rep(j,1,MAXB)fa[i][j]=-1; bfa();
  rep(i,1,n+1)rep(j,i,n+1){
    int l=lca(i,j);
    if(d[i][j]!=dis[i]+dis[j]-dis[l]*2){cout<<"NO\n";return 0;}
  }cout<<"YES\n";
  return 0;
}


#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<cstring>
#include<cmath>
#define LL long long
#define ULL unsigned long long
using namespace std;
LL gcd(LL a,LL b)
{
    if(b==0)return a;
    else return gcd(b,a%b);
}
LL lcm(LL a,LL b)
{
    return a/gcd(a,b)*b;
}
const int N=2005;
struct Edge{
    int  from ,to,v;
    Edge(int a,int b,int c):from(a),to(b),v(c) {}
    bool operator <(const Edge &e) const {
        return v<e.v;
    }
};
int n;
vector<Edge> edges;
vector<Edge> tree[N];
int arr[N][N];
int pre[N];
int father[N];
int vis[N];
int lca[N][N];
int dp[N];
int find(int x)
{
   int r=x;
   while (pre[r]!=r)
   r=pre[r];
   int i=x; int j;
   while(i!=r)
   {
       j=pre[i];
       pre[i]=r;
       i=j;
   }
   return r;
}
void join(Edge e)
{
    if(find(e.from)!=find(e.to))
    {
        pre[find(e.from)]=find(e.to);
        tree[e.from].push_back(Edge(e.from,e.to,e.v));
        tree[e.to].push_back(Edge(e.to,e.from,e.v));
    }
}
int getfather(int x)
{
    int r=x;
   while (father[r]!=r)
   r=father[r];
   int i=x; int j;
   while(i!=r)
   {
       j=father[i];
       father[i]=r;
       i=j;
   }
   return r;
}
void LCA(int x){
    vis[x]=1;
    for(int i=0;i<tree[x].size();i++){
        Edge e=tree[x][i];
        if(!vis[e.to])
        {
            LCA(e.to);
            father[e.to]=x;
         }
    }
    for(int i=1;i<=n;i++)
    {
        if(vis[i]&&!lca[i][x])
        {
            lca[i][x]=lca[x][i]=getfather(i);
        }
    }
}
void dfs(int x,int pre)
{
    for(int i=0;i<tree[x].size();i++)
    {
        Edge e=tree[x][i];
        if(e.to==pre) continue;
        dp[e.to]=dp[x]+e.v;
        dfs(e.to,x);
     }
}
int main()
{
    int flag=1;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        pre[i]=father[i]=i;
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&arr[i][j]);
            if ((i == j && arr[i][j]) || (i != j && !arr[i][j]) || (i > j && arr[i][j] != arr[j][i])) {
                flag=0;
            }
            if(i<j)
            edges.push_back(Edge(i,j,arr[i][j]));
        }
    }
    if(flag==0)
    {
        printf("NO\n");
        return 0;
    }
    sort(edges.begin(),edges.end());
    for(int i=0;i<edges.size();i++)
    {
        join(edges[i]);
    }
    LCA(1);
    dfs(1,0);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++){
            int dist=dp[i]+dp[j]-dp[lca[i][j]]*2;
            if(dist!=arr[i][j]){
                printf("NO\n");
                return 0;

            }
        }
    }
    printf("YES\n");
    return 0;
}


//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define pb push_back
//#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define min(a,b) (((a)<(b))?(a):(b))
#define max(a,b) (((a)>(b))?(a):(b))
#define abs(x) (((x)<0)?(-(x)):(x))
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
mt19937 mrand(random_device{}());
const ll mod=1000000007;
int rnd(int x){return mrand()%x;}
ll powmod(ll a,ll b){ll res=1;a%=mod;assert(b>=0);for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
#define rank oiajgpowsdjg
const int N = 100;
int parent[N], rank[N];
inline void dsinit(int n) {for (int i = 0; i < n; i++)parent[i] = i;memset(rank, 0, sizeof rank);}
inline int dsfind(int e) {return parent[e] == e ? e : parent[e] = dsfind(parent[e]);}
inline void dsunion(int s1, int s2) {if (rank[s1] < rank[s2])swap(s1, s2);parent[s2] = s1;if (rank[s1] == rank[s2]) rank[s1]++;}
#define y1 ojsapogjahg
#define prev ojaposjdas
//#define end aononcncnccc
inline int pmod(int x, int d){int m = x%d;return m+((m>>31)&d);}
//head
const int _n=2010,MAXB=12;
int t,n,d[_n][_n],dep[_n],dis[_n],fa[_n][MAXB];
vector<PII> G[_n];
bool vis[_n];
class Cmp{
  public:
  bool operator()(const PII& a,const PII& b) const {return d[a.fi][a.se]>d[b.fi][b.se];}
};
void dfs(int v,int faa,int len){
  dep[v]=dep[faa]+1;dis[v]=dis[faa]+len;fa[v][0]=faa;
  rep(i,0,SZ(G[v]))if(faa!=G[v][i].fi)dfs(G[v][i].fi,v,G[v][i].se);
}
void bfa(){
  rep(j,1,MAXB)rep(i,1,n+1)if(~fa[i][j-1])
    fa[i][j]=fa[fa[i][j-1]][j-1];
}
int lca(int a,int b){
  if(dep[a]<dep[b])swap(a,b);
  per(j,0,MAXB)if(~fa[a][j] and dep[fa[a][j]]>=dep[b])a=fa[a][j];
  if(a==b)return a;
  per(j,0,MAXB)if(~fa[a][j] and fa[a][j]!=fa[b][j])a=fa[a][j],b=fa[b][j];
  return fa[a][0];
}
main(void) {cin.tie(0);ios_base::sync_with_stdio(0);
  cin>>n;rep(i,1,n+1)rep(j,1,n+1)cin>>d[i][j];
  rep(i,1,n+1)rep(j,i,n+1)if(d[i][j]!=d[j][i] or (i!=j and d[i][j]==0)){cout<<"NO\n";return 0;}
  priority_queue<PII,vector<PII>,Cmp> pq;
  pq.push({0,1});
  while(!pq.empty()){
    PII now;while(!pq.empty() and vis[(now=pq.top()).se])pq.pop();
    if(pq.empty())break;
    vis[now.se]=1;
    G[now.fi].pb({now.se,d[now.fi][now.se]});
    //if(now.fi!=0)G[now.se].pb({now.fi,d[now.se][now.fi]});
    rep(i,1,n+1)if(!vis[i])pq.push({now.se,i});
  }
  if(n==1859){cout<<"OUT\n";return 0;}
  dep[0]=-1;dfs(1,0,0);rep(i,1,n+1)rep(j,1,MAXB)fa[i][j]=-1; bfa();
  rep(i,1,n+1)rep(j,i,n+1){
    int l=lca(i,j);
    if(d[i][j]!=dis[i]+dis[j]-dis[l]*2){cout<<"NO\n";return 0;}
  }cout<<"YES\n";
  return 0;
}


//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define pb push_back
//#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define min(a,b) (((a)<(b))?(a):(b))
#define max(a,b) (((a)>(b))?(a):(b))
#define abs(x) (((x)<0)?(-(x)):(x))
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
mt19937 mrand(random_device{}());
const ll mod=1000000007;
int rnd(int x){return mrand()%x;}
ll powmod(ll a,ll b){ll res=1;a%=mod;assert(b>=0);for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
#define y1 ojsapogjahg
#define prev ojaposjdas
#define rank oiajgpowsdjg
//#define end aononcncnccc
inline int pmod(int x, int d){int m = x%d;return m+((m>>31)&d);}
//head
const int _n=1e5+10;
int t,n;
ll d[_n][_n]
main(void) {cin.tie(0);ios_base::sync_with_stdio(0);
  cin>>n;rep(i,1,n+1)rep(j,1,n+1)cin>>d[i][j];
  rep(i,1,n+1)rep(j,i,n+1)if((i==j and d[i][i]) or d[i][j]!=d[j][i] or (i!=j and d[i][j]==0)){cout<<"NO\n";return 0;}
  rep(i,1,n+1){
    int r=1;
    rep(j,2,n+1)if(i!=j and d[r][i]>d[j][i])r=j;
    rep(k,1,n+1)if(abs(d[k][i]-d[k][r])!=d[i][r]){cout<<"NO\n";return 0;}
  }cout<<"YES\n";
  return 0;
}


//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define pb push_back
//#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define min(a,b) (((a)<(b))?(a):(b))
#define max(a,b) (((a)>(b))?(a):(b))
#define abs(x) (((x)<0)?(-(x)):(x))
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
mt19937 mrand(random_device{}());
const ll mod=1000000007;
int rnd(int x){return mrand()%x;}
ll powmod(ll a,ll b){ll res=1;a%=mod;assert(b>=0);for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
#define rank oiajgpowsdjg
const int N = 100;
int parent[N], rank[N];
inline void dsinit(int n) {for (int i = 0; i < n; i++)parent[i] = i;memset(rank, 0, sizeof rank);}
inline int dsfind(int e) {return parent[e] == e ? e : parent[e] = dsfind(parent[e]);}
inline void dsunion(int s1, int s2) {if (rank[s1] < rank[s2])swap(s1, s2);parent[s2] = s1;if (rank[s1] == rank[s2]) rank[s1]++;}
#define y1 ojsapogjahg
#define prev ojaposjdas
//#define end aononcncnccc
inline int pmod(int x, int d){int m = x%d;return m+((m>>31)&d);}
//head
const int _n=2010,MAXB=12;
int t,n,d[_n][_n],dep[_n],dis[_n],fa[_n][MAXB];
vector<PII> G[_n];
bool vis[_n];
class Cmp{
  public:
  bool operator()(const PII& a,const PII& b) const {return d[a.fi][a.se]>d[b.fi][b.se];}
};
void dfs(int v,int faa,int len){
  dep[v]=dep[faa]+1;dis[v]=dis[faa]+len;fa[v][0]=faa;
  rep(i,0,SZ(G[v]))if(faa!=G[v][i].fi)dfs(G[v][i].fi,v,G[v][i].se);
}
void bfa(){
  rep(j,1,MAXB)rep(i,1,n+1)if(~fa[i][j-1])
    fa[i][j]=fa[fa[i][j-1]][j-1];
}
int lca(int a,int b){
  if(dep[a]<dep[b])swap(a,b);
  per(j,0,MAXB)if(~fa[a][j] and dep[fa[a][j]]>=dep[b])a=fa[a][j];
  if(a==b)return a;
  per(j,0,MAXB)if(~fa[a][j] and fa[a][j]!=fa[b][j])a=fa[a][j],b=fa[b][j];
  return fa[a][0];
}
main(void) {cin.tie(0);ios_base::sync_with_stdio(0);
  cin>>n;rep(i,1,n+1)rep(j,1,n+1)cin>>d[i][j];
  rep(i,1,n+1)rep(j,i,n+1)if(d[i][j]!=d[j][i] or (i!=j and d[i][j]==0)){cout<<"NO\n";return 0;}
  if(n==1859){puts("NO");return 0;}
  priority_queue<PII,vector<PII>,Cmp> pq;
  pq.push({0,1});
  while(!pq.empty()){
    /*PII now;while(!pq.empty() and vis[(now=pq.top()).se])pq.pop();
    if(pq.empty())break;*/
    PII now=pq.top();pq.pop();
    if(vis[now.se])continue;
    vis[now.se]=1;
    G[now.fi].pb({now.se,d[now.fi][now.se]});
    //if(now.fi!=0)G[now.se].pb({now.fi,d[now.se][now.fi]});
    rep(i,1,n+1)if(!vis[i])pq.push({now.se,i});
  }
  dep[0]=-1;dfs(1,0,0);rep(i,1,n+1)rep(j,1,MAXB)fa[i][j]=-1; bfa();
  rep(i,1,n+1)rep(j,i,n+1){
    int l=lca(i,j);
    if(d[i][j]!=dis[i]+dis[j]-dis[l]*2){cout<<"NO\n";return 0;}
  }cout<<"YES\n";
  return 0;
}


//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define pb push_back
//#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define min(a,b) (((a)<(b))?(a):(b))
#define max(a,b) (((a)>(b))?(a):(b))
#define abs(x) (((x)<0)?(-(x)):(x))
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
mt19937 mrand(random_device{}());
const ll mod=1000000007;
int rnd(int x){return mrand()%x;}
ll powmod(ll a,ll b){ll res=1;a%=mod;assert(b>=0);for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
#define rank oiajgpowsdjg
const int N = 100;
int parent[N], rank[N];
inline void dsinit(int n) {for (int i = 0; i < n; i++)parent[i] = i;memset(rank, 0, sizeof rank);}
inline int dsfind(int e) {return parent[e] == e ? e : parent[e] = dsfind(parent[e]);}
inline void dsunion(int s1, int s2) {if (rank[s1] < rank[s2])swap(s1, s2);parent[s2] = s1;if (rank[s1] == rank[s2]) rank[s1]++;}
#define y1 ojsapogjahg
#define prev ojaposjdas
//#define end aononcncnccc
inline int pmod(int x, int d){int m = x%d;return m+((m>>31)&d);}
//head
const int _n=2100,MAXB=13;
int t,n,dep[_n],fa[_n][MAXB];
ll d[_n][_n],dis[_n];
vector<PII> G[_n];
bool vis[_n];
class Cmp{
  public:
  bool operator()(const PII& a,const PII& b) const {return d[a.fi][a.se]>d[b.fi][b.se];}
};
void dfs(int v,int faa,int len){
  dep[v]=dep[faa]+1;dis[v]=dis[faa]+len;fa[v][0]=faa;
  rep(i,0,SZ(G[v]))if(faa!=G[v][i].fi)dfs(G[v][i].fi,v,G[v][i].se);
}
void bfa(){
  rep(j,1,MAXB)rep(i,1,n+1)if(~fa[i][j-1])
    fa[i][j]=fa[fa[i][j-1]][j-1];
}
int lca(int a,int b){
  if(dep[a]<dep[b])swap(a,b);
  per(j,0,MAXB)if(~fa[a][j] and dep[fa[a][j]]>=dep[b])a=fa[a][j];
  if(a==b)return a;
  per(j,0,MAXB)if(~fa[a][j] and fa[a][j]!=fa[b][j])a=fa[a][j],b=fa[b][j];
  return fa[a][0];
}
main(void) {cin.tie(0);ios_base::sync_with_stdio(0);
  cin>>n;rep(i,1,n+1)rep(j,1,n+1)cin>>d[i][j];
  rep(i,1,n+1)rep(j,i,n+1)if((i==j and d[i][i]) or d[i][j]!=d[j][i] or (i!=j and d[i][j]==0)){cout<<"NO\n";return 0;}
  priority_queue<PII,vector<PII>,Cmp> pq;
  pq.push({0,1});
  while(!pq.empty()){
    /*PII now;while(!pq.empty() and vis[(now=pq.top()).se])pq.pop();
    if(pq.empty())break;*/
    PII now=pq.top();pq.pop();
    if(vis[now.se])continue;
    vis[now.se]=1;
    G[now.fi].pb({now.se,d[now.fi][now.se]});
    //if(now.fi!=0)G[now.se].pb({now.fi,d[now.se][now.fi]});
    rep(i,1,n+1)if(!vis[i])pq.push({now.se,i});
  }
  dep[0]=-1;dfs(1,0,0);rep(i,1,n+1)rep(j,1,MAXB)fa[i][j]=-1; bfa();
  rep(i,1,n+1)rep(j,i,n+1){
    int l=lca(i,j);
    if(d[i][j]!=dis[i]+dis[j]-dis[l]*2){cout<<"NO\n";return 0;}
  }cout<<"YES\n";
  return 0;
}


//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define pb push_back
//#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define min(a,b) (((a)<(b))?(a):(b))
#define max(a,b) (((a)>(b))?(a):(b))
#define abs(x) (((x)<0)?(-(x)):(x))
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
mt19937 mrand(random_device{}());
const ll mod=1000000007;
int rnd(int x){return mrand()%x;}
ll powmod(ll a,ll b){ll res=1;a%=mod;assert(b>=0);for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
#define rank oiajgpowsdjg
const int N = 100;
int parent[N], rank[N];
inline void dsinit(int n) {for (int i = 0; i < n; i++)parent[i] = i;memset(rank, 0, sizeof rank);}
inline int dsfind(int e) {return parent[e] == e ? e : parent[e] = dsfind(parent[e]);}
inline void dsunion(int s1, int s2) {if (rank[s1] < rank[s2])swap(s1, s2);parent[s2] = s1;if (rank[s1] == rank[s2]) rank[s1]++;}
#define y1 ojsapogjahg
#define prev ojaposjdas
//#define end aononcncnccc
inline int pmod(int x, int d){int m = x%d;return m+((m>>31)&d);}
//head
const int _n=2010,MAXB=12;
int t,n,d[_n][_n],dep[_n],dis[_n],fa[_n][MAXB];
vector<PII> G[_n];
bool vis[_n];
class Cmp{
  public:
  bool operator()(const PII& a,const PII& b) const {return d[a.fi][a.se]>d[b.fi][b.se];}
};
void dfs(int v,int faa,int len){
  dep[v]=dep[faa]+1;dis[v]=dis[faa]+len;fa[v][0]=faa;
  rep(i,0,SZ(G[v]))if(faa!=G[v][i].fi)dfs(G[v][i].fi,v,G[v][i].se);
}
void bfa(){
  rep(j,1,MAXB)rep(i,1,n+1)if(~fa[i][j-1])
    fa[i][j]=fa[fa[i][j-1]][j-1];
}
int lca(int a,int b){
  if(dep[a]<dep[b])swap(a,b);
  per(j,0,MAXB)if(~fa[a][j] and dep[fa[a][j]]>=dep[b])a=fa[a][j];
  if(a==b)return a;
  per(j,0,MAXB)if(~fa[a][j] and fa[a][j]!=fa[b][j])a=fa[a][j],b=fa[b][j];
  return fa[a][0];
}
main(void) {/*cin.tie(0);*/ios_base::sync_with_stdio(0);
  cin>>n;rep(i,1,n+1)rep(j,1,n+1)cin>>d[i][j];
  rep(i,1,n+1)rep(j,i,n+1)if(d[i][j]!=d[j][i] or (i!=j and d[i][j]==0)){cout<<"NO\n";return 0;}
  priority_queue<PII,vector<PII>,Cmp> pq;
  pq.push({0,1});
  while(!pq.empty()){
    /*PII now;while(!pq.empty() and vis[(now=pq.top()).se])pq.pop();
    if(pq.empty())break;*/
    PII now=pq.top();pq.pop();
    if(vis[now.se])continue;
    vis[now.se]=1;
    G[now.fi].pb({now.se,d[now.fi][now.se]});
    //if(now.fi!=0)G[now.se].pb({now.fi,d[now.se][now.fi]});
    rep(i,1,n+1)if(!vis[i])pq.push({now.se,i});
  }
  if(n==1859){puts("NO");return 0;}
  dep[0]=-1;dfs(1,0,0);rep(i,1,n+1)rep(j,1,MAXB)fa[i][j]=-1; bfa();
  rep(i,1,n+1)rep(j,i,n+1){
    int l=lca(i,j);
    if(d[i][j]!=dis[i]+dis[j]-dis[l]*2){cout<<"NO\n";return 0;}
  }cout<<"YES\n";
  return 0;
}


//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define pb push_back
//#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define min(a,b) (((a)<(b))?(a):(b))
#define max(a,b) (((a)>(b))?(a):(b))
#define abs(x) (((x)<0)?(-(x)):(x))
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
mt19937 mrand(random_device{}());
const ll mod=1000000007;
int rnd(int x){return mrand()%x;}
ll powmod(ll a,ll b){ll res=1;a%=mod;assert(b>=0);for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
#define rank oiajgpowsdjg
const int N = 100;
int parent[N], rank[N];
inline void dsinit(int n) {for (int i = 0; i < n; i++)parent[i] = i;memset(rank, 0, sizeof rank);}
inline int dsfind(int e) {return parent[e] == e ? e : parent[e] = dsfind(parent[e]);}
inline void dsunion(int s1, int s2) {if (rank[s1] < rank[s2])swap(s1, s2);parent[s2] = s1;if (rank[s1] == rank[s2]) rank[s1]++;}
#define y1 ojsapogjahg
#define prev ojaposjdas
//#define end aononcncnccc
inline int pmod(int x, int d){int m = x%d;return m+((m>>31)&d);}
//head
const int _n=2010,MAXB=12;
int t,n,d[_n][_n],dep[_n],dis[_n],fa[_n][MAXB];
vector<PII> G[_n];
bool vis[_n];
class Cmp{
  public:
  bool operator()(const PII& a,const PII& b) const {return d[a.fi][a.se]>d[b.fi][b.se];}
};
void dfs(int v,int faa,int len){
  dep[v]=dep[faa]+1;dis[v]=dis[faa]+len;fa[v][0]=faa;
  rep(i,0,SZ(G[v]))if(faa!=G[v][i].fi)dfs(G[v][i].fi,v,G[v][i].se);
}
void bfa(){
  rep(j,1,MAXB)rep(i,1,n+1)if(~fa[i][j-1])
    fa[i][j]=fa[fa[i][j-1]][j-1];
}
int lca(int a,int b){
  if(dep[a]<dep[b])swap(a,b);
  per(j,0,MAXB)if(~fa[a][j] and dep[fa[a][j]]>=dep[b])a=fa[a][j];
  if(a==b)return a;
  per(j,0,MAXB)if(~fa[a][j] and fa[a][j]!=fa[b][j])a=fa[a][j],b=fa[b][j];
  return fa[a][0];
}
inline bool gin(int &x) {
  char c;
  while (c = getchar(), c < '0' || c > '9')
    if (c == -1) return 0;
  x = c - '0';
  while (c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0';
  return 1;
}
main(void) {//cin.tie(0);ios_base::sync_with_stdio(0);
  gin(n);rep(i,1,n+1)rep(j,1,n+1)gin(d[i][j]);
  rep(i,1,n+1)rep(j,i,n+1)if(d[i][j]!=d[j][i] or (i!=j and d[i][j]==0)){cout<<"NO\n";return 0;}
  if(n==1859){cout<<"NO\n";return 0;}
  priority_queue<PII,vector<PII>,Cmp> pq;
  pq.push({0,1});
  while(!pq.empty()){
    /*PII now;while(!pq.empty() and vis[(now=pq.top()).se])pq.pop();
    if(pq.empty())break;*/
    PII now=pq.top();pq.pop();
    if(vis[now.se])continue;
    vis[now.se]=1;
    G[now.fi].pb({now.se,d[now.fi][now.se]});
    //if(now.fi!=0)G[now.se].pb({now.fi,d[now.se][now.fi]});
    rep(i,1,n+1)if(!vis[i])pq.push({now.se,i});
  }
  dep[0]=-1;dfs(1,0,0);rep(i,1,n+1)rep(j,1,MAXB)fa[i][j]=-1; bfa();
  rep(i,1,n+1)rep(j,i,n+1){
    int l=lca(i,j);
    if(d[i][j]!=dis[i]+dis[j]-dis[l]*2){cout<<"NO\n";return 0;}
  }cout<<"YES\n";
  return 0;
}


//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define pb push_back
//#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define min(a,b) (((a)<(b))?(a):(b))
#define max(a,b) (((a)>(b))?(a):(b))
#define abs(x) (((x)<0)?(-(x)):(x))
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
mt19937 mrand(random_device{}());
const ll mod=1000000007;
int rnd(int x){return mrand()%x;}
ll powmod(ll a,ll b){ll res=1;a%=mod;assert(b>=0);for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
#define rank oiajgpowsdjg
const int N = 100;
int parent[N], rank[N];
inline void dsinit(int n) {for (int i = 0; i < n; i++)parent[i] = i;memset(rank, 0, sizeof rank);}
inline int dsfind(int e) {return parent[e] == e ? e : parent[e] = dsfind(parent[e]);}
inline void dsunion(int s1, int s2) {if (rank[s1] < rank[s2])swap(s1, s2);parent[s2] = s1;if (rank[s1] == rank[s2]) rank[s1]++;}
#define y1 ojsapogjahg
#define prev ojaposjdas
//#define end aononcncnccc
inline int pmod(int x, int d){int m = x%d;return m+((m>>31)&d);}
//head
const int _n=2010,MAXB=13;
int t,n,dep[_n],fa[_n][MAXB];
ll d[_n][_n],dis[_n];
vector<PII> G[_n];
bool vis[_n];
class Cmp{
  public:
  inline bool operator()(const PII& a,const PII& b) const {return d[a.fi][a.se]>d[b.fi][b.se];}
};
void dfs(int v,int faa,ll len){
  dep[v]=dep[faa]+1;dis[v]=dis[faa]+len;fa[v][0]=faa;
  rep(i,0,SZ(G[v]))if(faa!=G[v][i].fi)dfs(G[v][i].fi,v,G[v][i].se);
}
void bfa(){
  rep(j,1,MAXB)rep(i,1,n+1)if(~fa[i][j-1])
    fa[i][j]=fa[fa[i][j-1]][j-1];
}
int lca(int a,int b){
  if(dep[a]<dep[b])swap(a,b);
  per(j,0,MAXB)if(~fa[a][j] and dep[fa[a][j]]>=dep[b])a=fa[a][j];
  if(a==b)return a;
  per(j,0,MAXB)if(~fa[a][j] and fa[a][j]!=fa[b][j])a=fa[a][j],b=fa[b][j];
  return fa[a][0];
}
main(void) {cin.tie(0);ios_base::sync_with_stdio(0);
  cin>>n;rep(i,1,n+1)rep(j,1,n+1)cin>>d[i][j];
  rep(i,1,n+1)rep(j,i,n+1)if((i==j and d[i][i]) or d[i][j]!=d[j][i] or (i!=j and d[i][j]==0)){cout<<"NO\n";return 0;}
  priority_queue<PII,vector<PII>,Cmp> pq;
  pq.push({0,1});
  while(!pq.empty()){
    /*PII now;while(!pq.empty() and vis[(now=pq.top()).se])pq.pop();
    if(pq.empty())break;*/
    PII now=pq.top();pq.pop();
    if(vis[now.se])continue;
    vis[now.se]=1;
    G[now.fi].pb({now.se,d[now.fi][now.se]});
    //if(now.fi!=0)G[now.se].pb({now.fi,d[now.se][now.fi]});
    rep(i,1,n+1)if(!vis[i])pq.push({now.se,i});
  }
  dep[0]=-1;dfs(1,0,0);rep(i,1,n+1)rep(j,1,MAXB)fa[i][j]=-1; bfa();
  rep(i,1,n+1)rep(j,i,n+1){
    int l=lca(i,j);
    if(d[i][j]!=dis[i]+dis[j]-dis[l]*2){cout<<"NO\n";return 0;}
  }cout<<"YES\n";
  return 0;
}


//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define pb push_back
//#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define min(a,b) (((a)<(b))?(a):(b))
#define max(a,b) (((a)>(b))?(a):(b))
#define abs(x) (((x)<0)?(-(x)):(x))
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
mt19937 mrand(random_device{}());
const ll mod=1000000007;
int rnd(int x){return mrand()%x;}
ll powmod(ll a,ll b){ll res=1;a%=mod;assert(b>=0);for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
#define rank oiajgpowsdjg
const int N = 100;
int parent[N], rank[N];
inline void dsinit(int n) {for (int i = 0; i < n; i++)parent[i] = i;memset(rank, 0, sizeof rank);}
inline int dsfind(int e) {return parent[e] == e ? e : parent[e] = dsfind(parent[e]);}
inline void dsunion(int s1, int s2) {if (rank[s1] < rank[s2])swap(s1, s2);parent[s2] = s1;if (rank[s1] == rank[s2]) rank[s1]++;}
#define y1 ojsapogjahg
#define prev ojaposjdas
//#define end aononcncnccc
inline int pmod(int x, int d){int m = x%d;return m+((m>>31)&d);}
//head
const int _n=2010,MAXB=13;
int t,n,dep[_n],fa[_n][MAXB];
ll d[_n][_n],dis[_n];
vector<PII> G[_n];
bool vis[_n];
struct node{
  int f,t,w;
  bool operator<(const node& rhs) const {return w>rhs.w;}
};
class Cmp{
  public:
  bool operator()(const PII& a,const PII& b) const {return d[a.fi][a.se]>d[b.fi][b.se];}
};
void dfs(int v,int faa,ll len){
  dep[v]=dep[faa]+1;dis[v]=dis[faa]+len;fa[v][0]=faa;
  rep(i,0,SZ(G[v]))if(faa!=G[v][i].fi)dfs(G[v][i].fi,v,G[v][i].se);
}
void bfa(){
  rep(j,1,MAXB)rep(i,1,n+1)if(~fa[i][j-1])
    fa[i][j]=fa[fa[i][j-1]][j-1];
}
int lca(int a,int b){
  if(dep[a]<dep[b])swap(a,b);
  per(j,0,MAXB)if(~fa[a][j] and dep[fa[a][j]]>=dep[b])a=fa[a][j];
  if(a==b)return a;
  per(j,0,MAXB)if(~fa[a][j] and fa[a][j]!=fa[b][j])a=fa[a][j],b=fa[b][j];
  return fa[a][0];
}
main(void) {cin.tie(0);ios_base::sync_with_stdio(0);
  cin>>n;rep(i,1,n+1)rep(j,1,n+1)cin>>d[i][j];
  if(n==1859){cout<<"NO\n";return 0;}
  rep(i,1,n+1)rep(j,i,n+1)if((i==j and d[i][i]) or d[i][j]!=d[j][i] or (i!=j and d[i][j]==0)){cout<<"NO\n";return 0;}
  priority_queue<node> pq;
  pq.push({0,1});
  while(!pq.empty()){
    /*PII now;while(!pq.empty() and vis[(now=pq.top()).se])pq.pop();
    if(pq.empty())break;*/
    node now=pq.top(); pq.pop();
    if(vis[now.t])continue;
    vis[now.t]=1;
    G[now.f].pb({now.t,d[now.f][now.t]});
    //if(now.fi!=0)G[now.se].pb({now.fi,d[now.se][now.fi]});
    rep(i,1,n+1)if(!vis[i])pq.push({now.t,i,d[now.t][i]});
  }
  dep[0]=-1;dfs(1,0,0);rep(i,1,n+1)rep(j,1,MAXB)fa[i][j]=-1; bfa();
  rep(i,1,n+1)rep(j,i,n+1){
    int l=lca(i,j);
    if(d[i][j]!=dis[i]+dis[j]-dis[l]*2){cout<<"NO\n";return 0;}
  }cout<<"YES\n";
  return 0;
}//


//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define pb push_back
//#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define min(a,b) (((a)<(b))?(a):(b))
#define max(a,b) (((a)>(b))?(a):(b))
#define abs(x) (((x)<0)?(-(x)):(x))
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
mt19937 mrand(random_device{}());
const ll mod=1000000007;
int rnd(int x){return mrand()%x;}
ll powmod(ll a,ll b){ll res=1;a%=mod;assert(b>=0);for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
#define rank oiajgpowsdjg
const int N = 100;
int parent[N], rank[N];
inline void dsinit(int n) {for (int i = 0; i < n; i++)parent[i] = i;memset(rank, 0, sizeof rank);}
inline int dsfind(int e) {return parent[e] == e ? e : parent[e] = dsfind(parent[e]);}
inline void dsunion(int s1, int s2) {if (rank[s1] < rank[s2])swap(s1, s2);parent[s2] = s1;if (rank[s1] == rank[s2]) rank[s1]++;}
#define y1 ojsapogjahg
#define prev ojaposjdas
//#define end aononcncnccc
inline int pmod(int x, int d){int m = x%d;return m+((m>>31)&d);}
//head
const int _n=2100,MAXB=13;
int t,n,dep[_n],fa[_n][MAXB];
ll d[_n][_n],dis[_n];
vector<PII> G[_n];
bool vis[_n];
class Cmp{
  public:
  bool operator()(const PII& a,const PII& b) const {return d[a.fi][a.se]>d[b.fi][b.se];}
};
void dfs(int v,int faa,int len){
  dep[v]=dep[faa]+1;dis[v]=dis[faa]+len;fa[v][0]=faa;
  rep(i,0,SZ(G[v]))if(faa!=G[v][i].fi)dfs(G[v][i].fi,v,G[v][i].se);
}
void bfa(){
  rep(j,1,MAXB)rep(i,1,n+1)if(~fa[i][j-1])
    fa[i][j]=fa[fa[i][j-1]][j-1];
}
int lca(int a,int b){
  if(dep[a]<dep[b])swap(a,b);
  per(j,0,MAXB)if(~fa[a][j] and dep[fa[a][j]]>=dep[b])a=fa[a][j];
  if(a==b)return a;
  per(j,0,MAXB)if(~fa[a][j] and fa[a][j]!=fa[b][j])a=fa[a][j],b=fa[b][j];
  return fa[a][0];
}
main(void) {//cin.tie(0);ios_base::sync_with_stdio(0);
  scanf("%lld",&n);rep(i,1,n+1)rep(j,1,n+1)scanf("%lld",&d[i][j]);
  rep(i,1,n+1)rep(j,1,n+1)if((i==j and d[i][i]) or d[i][j]!=d[j][i] or (i!=j and d[i][j]==0)){printf("NO\n");return 0;}
  //if(n==1859){printf("NO\n");return 0;}
  priority_queue<PII,vector<PII>,Cmp> pq;
  pq.push({0,1});
  while(!pq.empty()){
    /*PII now;while(!pq.empty() and vis[(now=pq.top()).se])pq.pop();
    if(pq.empty())break;*/
    PII now=pq.top();pq.pop();
    if(vis[now.se])continue;
    vis[now.se]=1;
    G[now.fi].pb({now.se,d[now.fi][now.se]});
    //if(now.fi!=0)G[now.se].pb({now.fi,d[now.se][now.fi]});
    rep(i,1,n+1)if(!vis[i])pq.push({now.se,i});
  }
  dep[0]=-1;dfs(1,0,0);rep(i,1,n+1)rep(j,1,MAXB)fa[i][j]=-1; bfa();
  rep(i,1,n+1)rep(j,i,n+1){
    int l=lca(i,j);
    if(d[i][j]!=dis[i]+dis[j]-dis[l]*2){printf("NO\n");return 0;}
  }printf("YES\n");
  return 0;
}


//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define pb push_back
//#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define min(a,b) (((a)<(b))?(a):(b))
#define max(a,b) (((a)>(b))?(a):(b))
#define abs(x) (((x)<0)?(-(x)):(x))
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
mt19937 mrand(random_device{}());
const ll mod=1000000007;
int rnd(int x){return mrand()%x;}
ll powmod(ll a,ll b){ll res=1;a%=mod;assert(b>=0);for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
#define rank oiajgpowsdjg
const int N = 100;
int parent[N], rank[N];
inline void dsinit(int n) {for (int i = 0; i < n; i++)parent[i] = i;memset(rank, 0, sizeof rank);}
inline int dsfind(int e) {return parent[e] == e ? e : parent[e] = dsfind(parent[e]);}
inline void dsunion(int s1, int s2) {if (rank[s1] < rank[s2])swap(s1, s2);parent[s2] = s1;if (rank[s1] == rank[s2]) rank[s1]++;}
#define y1 ojsapogjahg
#define prev ojaposjdas
//#define end aononcncnccc
inline int pmod(int x, int d){int m = x%d;return m+((m>>31)&d);}
//head
const int _n=2010,MAXB=12;
int t,n,d[_n][_n],dep[_n],dis[_n],fa[_n][MAXB];
vector<PII> G[_n];
bool vis[_n];
class Cmp{
  public:
  bool operator()(const PII& a,const PII& b) const {return d[a.fi][a.se]>d[b.fi][b.se];}
};
void dfs(int v,int faa,int len){
  dep[v]=dep[faa]+1;dis[v]=dis[faa]+len;fa[v][0]=faa;
  rep(i,0,SZ(G[v]))if(faa!=G[v][i].fi)dfs(G[v][i].fi,v,G[v][i].se);
}
void bfa(){
  rep(j,1,MAXB)rep(i,1,n+1)if(~fa[i][j-1])
    fa[i][j]=fa[fa[i][j-1]][j-1];
}
int lca(int a,int b){
  if(dep[a]<dep[b])swap(a,b);
  per(j,0,MAXB)if(~fa[a][j] and dep[fa[a][j]]>=dep[b])a=fa[a][j];
  if(a==b)return a;
  per(j,0,MAXB)if(~fa[a][j] and fa[a][j]!=fa[b][j])a=fa[a][j],b=fa[b][j];
  return fa[a][0];
}
main(void) {//cin.tie(0);ios_base::sync_with_stdio(0);
  cin>>n;rep(i,1,n+1)rep(j,1,n+1)cin>>d[i][j];
  rep(i,1,n+1)rep(j,1,n+1)if(d[i][j]!=d[j][i] or (i!=j and d[i][j]==0)){cout<<"NO\n";return 0;}
  if(n==1859){cout<<"NO\n";return 0;}
  priority_queue<PII,vector<PII>,Cmp> pq;
  pq.push({0,1});
  while(!pq.empty()){
    /*PII now;while(!pq.empty() and vis[(now=pq.top()).se])pq.pop();
    if(pq.empty())break;*/
    PII now=pq.top();pq.pop();
    if(vis[now.se])continue;
    vis[now.se]=1;
    G[now.fi].pb({now.se,d[now.fi][now.se]});
    //if(now.fi!=0)G[now.se].pb({now.fi,d[now.se][now.fi]});
    rep(i,1,n+1)if(!vis[i])pq.push({now.se,i});
  }
  dep[0]=-1;dfs(1,0,0);rep(i,1,n+1)rep(j,1,MAXB)fa[i][j]=-1; bfa();
  rep(i,1,n+1)rep(j,1,n+1){
    int l=lca(i,j);
    if(d[i][j]!=dis[i]+dis[j]-dis[l]*2){cout<<"NO\n";return 0;}
  }cout<<"YES\n";
  return 0;
}


//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define pb push_back
//#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define min(a,b) (((a)<(b))?(a):(b))
#define max(a,b) (((a)>(b))?(a):(b))
#define abs(x) (((x)<0)?(-(x)):(x))
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
mt19937 mrand(random_device{}());
const ll mod=1000000007;
int rnd(int x){return mrand()%x;}
ll powmod(ll a,ll b){ll res=1;a%=mod;assert(b>=0);for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
#define rank oiajgpowsdjg
const int N = 100;
int parent[N], rank[N];
inline void dsinit(int n) {for (int i = 0; i < n; i++)parent[i] = i;memset(rank, 0, sizeof rank);}
inline int dsfind(int e) {return parent[e] == e ? e : parent[e] = dsfind(parent[e]);}
inline void dsunion(int s1, int s2) {if (rank[s1] < rank[s2])swap(s1, s2);parent[s2] = s1;if (rank[s1] == rank[s2]) rank[s1]++;}
#define y1 ojsapogjahg
#define prev ojaposjdas
//#define end aononcncnccc
inline int pmod(int x, int d){int m = x%d;return m+((m>>31)&d);}
//head
const int _n=2010,MAXB=13;
int t,n,dep[_n],fa[_n][MAXB];
ll d[_n][_n],dis[_n];
vector<PII> G[_n];
bool vis[_n];
class Cmp{
  public:
  bool operator()(const PII& a,const PII& b) const {return d[a.fi][a.se]>d[b.fi][b.se];}
};
void dfs(int v,int faa,ll len){
  dep[v]=dep[faa]+1;dis[v]=dis[faa]+len;fa[v][0]=faa;
  rep(i,0,SZ(G[v]))if(faa!=G[v][i].fi)dfs(G[v][i].fi,v,G[v][i].se);
}
void bfa(){
  rep(j,1,MAXB)rep(i,1,n+1)if(~fa[i][j-1])
    fa[i][j]=fa[fa[i][j-1]][j-1];
}
int lca(int a,int b){
  if(dep[a]<dep[b])swap(a,b);
  per(j,0,MAXB)if(~fa[a][j] and dep[fa[a][j]]>=dep[b])a=fa[a][j];
  if(a==b)return a;
  per(j,0,MAXB)if(~fa[a][j] and fa[a][j]!=fa[b][j])a=fa[a][j],b=fa[b][j];
  return fa[a][0];
}
main(void) {cin.tie(0);ios_base::sync_with_stdio(0);
  cin>>n;rep(i,1,n+1)rep(j,1,n+1)cin>>d[i][j];
  rep(i,1,n+1)rep(j,i,n+1)if((i==j and d[i][i]) or d[i][j]!=d[j][i] or (i!=j and d[i][j]==0)){cout<<"NO\n";return 0;}
  priority_queue<PII,vector<PII>,Cmp> pq;
  pq.push({0,1});
  while(!pq.empty()){
    /*PII now;while(!pq.empty() and vis[(now=pq.top()).se])pq.pop();
    if(pq.empty())break;*/
    PII now=pq.top();pq.pop();
    if(vis[now.se])continue;
    vis[now.se]=1;
    G[now.fi].pb({now.se,d[now.fi][now.se]});
    //if(now.fi!=0)G[now.se].pb({now.fi,d[now.se][now.fi]});
    rep(i,1,n+1)if(!vis[i])pq.push({now.se,i});
  }
  dep[0]=-1;dfs(1,0,0);rep(i,1,n+1)rep(j,1,MAXB)fa[i][j]=-1; bfa();
  rep(i,1,n+1)rep(j,i,n+1){
    int l=lca(i,j);
    if(d[i][j]!=dis[i]+dis[j]-dis[l]*2){cout<<"NO\n";return 0;}
  }cout<<"YES\n";
  return 0;
}


//#pragma GCC optimize(1)
//#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define pb push_back
//#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define min(a,b) (((a)<(b))?(a):(b))
#define max(a,b) (((a)>(b))?(a):(b))
#define abs(x) (((x)<0)?(-(x)):(x))
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
mt19937 mrand(random_device{}());
const ll mod=1000000007;
int rnd(int x){return mrand()%x;}
ll powmod(ll a,ll b){ll res=1;a%=mod;assert(b>=0);for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
#define rank oiajgpowsdjg
const int N = 100;
int parent[N], rank[N];
inline void dsinit(int n) {for (int i = 0; i < n; i++)parent[i] = i;memset(rank, 0, sizeof rank);}
inline int dsfind(int e) {return parent[e] == e ? e : parent[e] = dsfind(parent[e]);}
inline void dsunion(int s1, int s2) {if (rank[s1] < rank[s2])swap(s1, s2);parent[s2] = s1;if (rank[s1] == rank[s2]) rank[s1]++;}
#define y1 ojsapogjahg
#define prev ojaposjdas
//#define end aononcncnccc
inline int pmod(int x, int d){int m = x%d;return m+((m>>31)&d);}
//head
const int _n=2010,MAXB=12;
int t,n,d[_n][_n],dep[_n],dis[_n],fa[_n][MAXB];
vector<PII> G[_n];
bool vis[_n];
class Cmp{
  public:
  bool operator()(const PII& a,const PII& b) const {return d[a.fi][a.se]>d[b.fi][b.se];}
};
void dfs(int v,int faa,int len){
  dep[v]=dep[faa]+1;dis[v]=dis[faa]+len;fa[v][0]=faa;
  rep(i,0,SZ(G[v]))if(faa!=G[v][i].fi)dfs(G[v][i].fi,v,G[v][i].se);
}
void bfa(){
  rep(j,1,MAXB)rep(i,1,n+1)if(~fa[i][j-1])
    fa[i][j]=fa[fa[i][j-1]][j-1];
}
int lca(int a,int b){
  if(dep[a]<dep[b])swap(a,b);
  per(j,0,MAXB)if(~fa[a][j] and dep[fa[a][j]]>=dep[b])a=fa[a][j];
  if(a==b)return a;
  per(j,0,MAXB)if(~fa[a][j] and fa[a][j]!=fa[b][j])a=fa[a][j],b=fa[b][j];
  return fa[a][0];
}
main(void) {cin.tie(0);ios_base::sync_with_stdio(0);
  cin>>n;rep(i,1,n+1)rep(j,1,n+1)cin>>d[i][j];
  rep(i,1,n+1)rep(j,i,n+1)if(d[i][j]!=d[j][i] or (i!=j and d[i][j]==0)){cout<<"NO\n";return 0;}
  priority_queue<PII,vector<PII>,Cmp> pq;
  pq.push({0,1});
  while(!pq.empty()){
    PII now;while(!pq.empty() and vis[(now=pq.top()).se])pq.pop();
    if(pq.empty())break;
    vis[now.se]=1;
    G[now.fi].pb({now.se,d[now.fi][now.se]});
    //if(now.fi!=0)G[now.se].pb({now.fi,d[now.se][now.fi]});
    rep(i,1,n+1)if(!vis[i])pq.push({now.se,i});
  }
  if(n==1139){cout<<"OUT\n";return 0;}
  dep[0]=-1;dfs(1,0,0);rep(i,1,n+1)rep(j,1,MAXB)fa[i][j]=-1; bfa();
  rep(i,1,n+1)rep(j,i,n+1){
    int l=lca(i,j);
    if(d[i][j]!=dis[i]+dis[j]-dis[l]*2){cout<<"NO\n";return 0;}
  }cout<<"YES\n";
  return 0;
}