#define speed ios::sync_with_stdio(false)
#include<bits/stdc++.h>

#define ll long long
#define ld long double
#define mod 1000000007
#define nax 1000005
#define inf 100000000000000000LL
#define pb push_back
#define mp make_pair
#define in insert
#define ff first
#define ss second
#define pll pair<ll,ll>
#define vll vector<ll>
#define vb vector<bool>
#define sll set<ll>
#define mll map<ll,ll>
#define mis map<int,string>
#define all(n) n.begin(),n.end()
#define tr(container, it) for(__typeof(container.begin()) it = container.begin(); it != container.end(); it++)
#define lpl(i,a,b) for(ll i=a;i<=b;++i)
#define lplr(i,a,b) for(ll i=a;i>=b;--i)
#define lpv(c,it) for(vii::iterator it=(c).begin();it!=(c).end();it++)
#define test() int t; cin >> t; while(t--)

using namespace std;
const int N = 2e3+3;

ll arr[N], s[N], w[N][N], depth[N], parent[N][16], dist[N][16];
bool done[N][N], vis[N];
vector<pll > adj[N];

struct tree
{
	ll x,y,wt;
};
bool cmp(tree a,tree b)
{
	if(a.wt < b.wt)
		return true;
	return false;
}
void init()
{
	lpl(i,0,N-1)
	{
		s[i] = 1;
		arr[i] = i;
	}
}
ll root(ll i)
{
	while(arr[i] != i)
		i = arr[arr[i]];
	return i;
}

void dfs(ll curr,ll prev)
{
	vis[curr] = true;
	depth[curr] = depth[prev]+1;
	parent[curr][0] = prev;
	for(auto i: adj[curr])
	{
		if(!vis[i.ff])
		{
			dist[i.ff][0] = i.ss;
			dfs(i.ff, curr);
		}
	}
}
void fill_parent(ll n)
{
	lpl(i,1,15)
	{
		lpl(j,1,n)
		{
			dist[j][i] = dist[j][i-1]+dist[parent[j][i-1]][i-1];
			parent[j][i] = parent[parent[j-1][i-1]][i-1];
		}
	}
}
ll lca(ll x,ll y)
{
	if(depth[x] > depth[y])
		swap(x,y);
	ll diff = depth[y]-depth[x];
	ll ans=0; // weight of the path from x->y
	lpl(i,0,15)
	{
		if(diff&(1<<i))
		{
			ans += dist[y][i];
			y = parent[y][i];
		}
	}
	if(x == y)
		return ans;
	lplr(i,15,0)
	{
		if(parent[x][i] != parent[y][i])
		{
			ans += dist[x][i], ans += dist[y][i];
			x = parent[x][i], y = parent[y][i];
		}
	}
	ans += dist[x][0], ans += dist[y][0];
	return ans;
}

int main()
{
	speed;
	ll n;
	cin >> n;
	vector<tree> ar;
	tree obj;
	lpl(i,1,n)
	{
		lpl(j,1,n)
		{
			cin >> w[i][j];
			if(i==j && w[i][j]!=0)
			{
				cout << "NO";
				return 0;
			}
			if(i!=j && w[i][j]==0)
			{
				cout << "NO";
				return 0;
			}
			obj.x=i, obj.y=j, obj.wt=w[i][j];
			ar.pb(obj);
		}
	}
	lpl(i,1,n)
	{
		lpl(j,1,n)
		{
			if(w[i][j] != w[j][i])
			{
				cout << "NO";
				return 0;
			}
		}
	}
	sort(all(ar), cmp);
	ll siz = ar.size();
	init();
	lpl(i,0,siz-1)
	{
		ll x = ar[i].x, y = ar[i].y, wt = ar[i].wt;
		ll root_x = root(x), root_y = root(y);
		if(root_x == root_y)
			continue;
		if(s[root_x] < s[root_y])
		{
			arr[root_x] = arr[root_y];
			s[root_y] += s[root_x];
		}
		else
		{
			arr[root_y] = arr[root_x];
			s[root_x] += s[root_y];
		}
		adj[x].pb({y,wt});
		adj[y].pb({x,wt});
		done[x][y] = true;
	}
	dfs(1,0);
	fill_parent(n);

	lpl(i,1,n)
	{
		lpl(j,1,n)
		{
			ll z = lca(i,j);
			if(w[i][j] == z)
			{
				continue;
			}
			cout << "NO" ;
			return 0;
		}
	}
	cout << "YES";
	return 0;
}


#define speed ios::sync_with_stdio(false)
#include<bits/stdc++.h>

#define ll long long
#define ld long double
#define mod 1000000007
#define nax 1000005
#define inf 100000000000000000LL
#define pb push_back
#define mp make_pair
#define in insert
#define ff first
#define ss second
#define pll pair<ll,ll>
#define vll vector<ll>
#define vb vector<bool>
#define sll set<ll>
#define mll map<ll,ll>
#define mis map<int,string>
#define all(n) n.begin(),n.end()
#define tr(container, it) for(__typeof(container.begin()) it = container.begin(); it != container.end(); it++)
#define lpl(i,a,b) for(ll i=a;i<=b;++i)
#define lplr(i,a,b) for(ll i=a;i>=b;--i)
#define lpv(c,it) for(vii::iterator it=(c).begin();it!=(c).end();it++)
#define test() int t; cin >> t; while(t--)

using namespace std;
const int N = 2e3+3;

ll arr[N], s[N], w[N][N], depth[N], parent[N][16], dist[N][16];
bool done[N][N], vis[N];
vector<pll > adj[N];

struct tree
{
	ll x,y,wt;
};
bool cmp(tree a,tree b)
{
	if(a.wt < b.wt)
		return true;
	return false;
}
void init()
{
	lpl(i,0,N-1)
	{
		s[i] = 1;
		arr[i] = i;
	}
}
ll root(ll i)
{
	while(arr[i] != i)
		i = arr[arr[i]];
	return i;
}

void dfs(ll curr,ll prev)
{
	vis[curr] = true;
	depth[curr] = depth[prev]+1;
	parent[curr][0] = prev;
	for(auto i: adj[curr])
	{
		if(!vis[i.ff])
		{
			dist[i.ff][0] = i.ss;
			dfs(i.ff, curr);
		}
	}
}
void fill_parent(ll n)
{
	lpl(i,1,15)
	{
		lpl(j,1,n)
		{
			dist[j][i] = dist[j][i-1]+dist[parent[j][i-1]][i-1];
			parent[j][i] = parent[parent[j-1][i-1]][i-1];
		}
	}
}
ll lca(ll x,ll y)
{
	if(depth[x] > depth[y])
		swap(x,y);
	ll diff = depth[y]-depth[x];
	ll ans=0; // weight of the path from x->y
	lpl(i,0,15)
	{
		if(diff&(1<<i))
		{
			ans += dist[y][i];
			y = parent[y][i];
		}
	}
	if(x == y)
		return ans;
	lplr(i,15,0)
	{
		if(parent[x][i] != parent[y][i])
		{
			ans += dist[x][i], ans += dist[y][i];
			x = parent[x][i], y = parent[y][i];
		}
	}
	ans += dist[x][0], ans += dist[y][0];
	return ans;
}

int main()
{
	speed;
	ll n;
	cin >> n;
	vector<tree> ar;
	tree obj;
	lpl(i,1,n)
	{
		lpl(j,1,n)
		{
			cin >> w[i][j];
			if(i==j && w[i][j]!=0)
			{
				cout << "NO";
				return 0;
			}
			if(i!=j && w[i][j]==0)
			{
				cout << "NO";
				return 0;
			}
			obj.x=i, obj.y=j, obj.wt=w[i][j];
			ar.pb(obj);
		}
	}
	lpl(i,1,n)
	{
		lpl(j,1,n)
		{
			if(w[i][j] != w[j][i])
			{
				cout << "NO";
				return 0;
			}
		}
	}
	sort(all(ar), cmp);
	ll siz = ar.size();
	init();
	lpl(i,0,siz-1)
	{
		ll x = ar[i].x, y = ar[i].y, wt = ar[i].wt;
		ll root_x = root(x), root_y = root(y);
		if(root_x == root_y)
			continue;
		if(s[root_x] < s[root_y])
		{
			arr[root_x] = arr[root_y];
			s[root_y] += s[root_x];
		}
		else
		{
			arr[root_y] = arr[root_x];
			s[root_x] += s[root_y];
		}
		adj[x].pb({y,wt});
		adj[y].pb({x,wt});
		done[x][y] = true;
	}
	dfs(1,0);
	fill_parent(n);

	lpl(i,1,n)
	{
		lpl(j,1,n)
		{
			if(done[i][j])
				continue;
			ll z = lca(i,j);
			if(w[i][j] == z)
			{
				done[i][j] = true;
				continue;
			}
			cout << "NO" ;
			return 0;
		}
	}
	cout << "YES";
	return 0;
}


#define speed ios::sync_with_stdio(false)
#include<bits/stdc++.h>

#define ll long long
#define ld long double
#define mod 1000000007
#define nax 1000005
#define inf 100000000000000000LL
#define pb push_back
#define mp make_pair
#define in insert
#define ff first
#define ss second
#define pll pair<ll,ll>
#define vll vector<ll>
#define vb vector<bool>
#define sll set<ll>
#define mll map<ll,ll>
#define mis map<int,string>
#define all(n) n.begin(),n.end()
#define tr(container, it) for(__typeof(container.begin()) it = container.begin(); it != container.end(); it++)
#define lpl(i,a,b) for(ll i=a;i<=b;++i)
#define lplr(i,a,b) for(ll i=a;i>=b;--i)
#define lpv(c,it) for(vii::iterator it=(c).begin();it!=(c).end();it++)
#define test() int t; cin >> t; while(t--)

using namespace std;
const int N = 2e3+9;

ll arr[N], s[N], w[N][N], depth[N], parent[N][16], dist[N][16];
bool done[N][N], vis[N];
vector<pll > adj[N];

struct tree
{
	ll x,y,wt;
};
bool cmp(tree a,tree b)
{
	if(a.wt < b.wt)
		return true;
	return false;
}
void init()
{
	lpl(i,0,N-1)
	{
		s[i] = 1;
		arr[i] = i;
	}
}
ll root(ll i)
{
	while(arr[i] != i)
		i = arr[arr[i]];
	return i;
}

void dfs(ll curr,ll prev)
{
	vis[curr] = true;
	depth[curr] = depth[prev]+1;
	parent[curr][0] = prev;
	for(auto i: adj[curr])
	{
		if(!vis[i.ff])
		{
			dist[i.ff][0] = i.ss;
			dfs(i.ff, curr);
		}
	}
}
void fill_parent(ll n)
{
	lpl(i,1,15)
	{
		lpl(j,1,n)
		{
			dist[j][i] = dist[j][i-1]+dist[parent[j][i-1]][i-1];
			parent[j][i] = parent[parent[j][i-1]][i-1];
		}
	}
}
ll lca(ll x,ll y)
{
	if(depth[x] > depth[y])
		swap(x,y);
	ll diff = depth[y]-depth[x];
	ll ans=0; // weight of the path from x->y
	lpl(i,0,15)
	{
		if(diff&(1<<i))
		{
			ans += dist[y][i];
			y = parent[y][i];
		}
	}
	if(x == y)
		return ans;
	lplr(i,15,0)
	{
		if(parent[x][i] != parent[y][i])
		{
			ans += dist[x][i], ans += dist[y][i];
			x = parent[x][i], y = parent[y][i];
		}
	}
	ans += dist[x][0], ans += dist[y][0];
	return ans;
}

int main()
{
	speed;
	ll n;
	cin >> n;
	vector<tree> ar;
	tree obj;
	lpl(i,1,n)
	{
		lpl(j,1,n)
		{
			cin >> w[i][j];
			if(i!=j && w[i][j]==0)
			{
				cout << "NO";
				return 0;
			}
			if(i==j && w[i][j]!=0)
			{
				cout << "NO";
				return 0;
			}
			obj.x=i, obj.y=j, obj.wt=w[i][j];
			ar.pb(obj);
		}
	}
	lpl(i,1,n)
	{
		lpl(j,1,n)
		{
			if(w[i][j] != w[j][i])
			{
				cout << "NO";
				return 0;
			}

		}
	}
	sort(all(ar), cmp);
	ll siz = ar.size();
	init();
	lpl(i,0,siz-1)
	{
		ll x = ar[i].x, y = ar[i].y, wt = ar[i].wt;
		ll root_x = root(x), root_y = root(y);
		if(root_x == root_y)
			continue;
		if(s[root_x] < s[root_y])
		{
			arr[root_x] = arr[root_y];
			s[root_y] += s[root_x];
		}
		else
		{
			arr[root_y] = arr[root_x];
			s[root_x] += s[root_y];
		}
		adj[x].pb({y,wt});
		adj[y].pb({x,wt});
		done[x][y] = done[y][x] = true;
	}
	/* MST ->
	lpl(i,1,n)
	{
		cout << i << " - > ";
		for(auto x: adj[i])
			cout << x.ff << " " << x.ss << endl;
	}*/
	dfs(1,0);

	fill_parent(n);

	lpl(i,1,n)
	{
		lpl(j,1,n)
		{
			if(done[i][j])
				continue;
			ll z = lca(i,j);
			if(w[i][j] == z)
			{
				done[i][j] = done[j][i] = true;
				continue;
			}
			//cout <<i << " "<<j << " "<< z <<" " << w[i][j] << endl;
			cout << "NO" ;
			return 0;
		}
	}
	cout << "YES";
	return 0;
}


#define speed ios::sync_with_stdio(false)
#include<bits/stdc++.h>

#define ll long long
#define ld long double
#define mod 1000000007
#define nax 1000005
#define inf 100000000000000000LL
#define pb push_back
#define mp make_pair
#define in insert
#define ff first
#define ss second
#define pll pair<ll,ll>
#define vll vector<ll>
#define vb vector<bool>
#define sll set<ll>
#define mll map<ll,ll>
#define mis map<int,string>
#define all(n) n.begin(),n.end()
#define tr(container, it) for(__typeof(container.begin()) it = container.begin(); it != container.end(); it++)
#define lpl(i,a,b) for(ll i=a;i<=b;++i)
#define lplr(i,a,b) for(ll i=a;i>=b;--i)
#define lpv(c,it) for(vii::iterator it=(c).begin();it!=(c).end();it++)
#define test() int t; cin >> t; while(t--)

using namespace std;
const int N = 2e3+9;

ll arr[N], s[N], w[N][N], depth[N], parent[N][20], dist[N][20];
bool done[N][N], vis[N];
vector<pll > adj[N];

struct tree
{
	ll x,y,wt;
};
bool cmp(tree a,tree b)
{
	if(a.wt < b.wt)
		return true;
	return false;
}
void init()
{
	lpl(i,0,N-1)
	{
		s[i] = 1;
		arr[i] = i;
	}
}
ll root(ll i)
{
	while(arr[i] != i)
		i = arr[arr[i]];
	return i;
}

void dfs(ll curr,ll prev)
{
	vis[curr] = true;
	depth[curr] = depth[prev]+1;
	parent[curr][0] = prev;
	for(auto i: adj[curr])
	{
		if(!vis[i.ff])
		{
			dist[i.ff][0] = i.ss;
			dfs(i.ff, curr);
		}
	}
}
void fill_parent(ll n)
{
	lpl(i,1,19)
	{
		lpl(j,1,n)
		{
			dist[j][i] = dist[j][i-1]+dist[parent[j][i-1]][i-1];
			parent[j][i] = parent[parent[j][i-1]][i-1];
		}
	}
}
ll lca(ll x,ll y)
{
	if(depth[x] > depth[y])
		swap(x,y);
	ll diff = depth[y]-depth[x];
	ll ans=0; // weight of the path from x->y
	lpl(i,0,19)
	{
		if(diff&(1<<i))
		{
			ans += dist[y][i];
			y = parent[y][i];
		}
	}
	if(x == y)
		return ans;
	lplr(i,19,0)
	{
		if(parent[x][i] != parent[y][i])
		{
			ans += dist[x][i], ans += dist[y][i];
			x = parent[x][i], y = parent[y][i];
		}
	}
	ans += dist[x][0], ans += dist[y][0];
	return ans;
}

int main()
{
	speed;
	ll n;
	cin >> n;
	vector<tree> ar;
	tree obj;
	lpl(i,1,n)
	{
		lpl(j,1,n)
		{
			cin >> w[i][j];
			if(i!=j && w[i][j]==0)
			{
				cout << "NO";
				return 0;
			}
			if(i==j && w[i][j]!=0)
			{
				cout << "NO";
				return 0;
			}
			obj.x=i, obj.y=j, obj.wt=w[i][j];
			ar.pb(obj);
		}
	}
	lpl(i,1,n)
	{
		lpl(j,1,n)
		{
			if(w[i][j] != w[j][i])
			{
				cout << "NO";
				return 0;
			}

		}
	}
	sort(all(ar), cmp);
	ll siz = ar.size();
	init();
	lpl(i,0,siz-1)
	{
		ll x = ar[i].x, y = ar[i].y, wt = ar[i].wt;
		ll root_x = root(x), root_y = root(y);
		if(root_x == root_y)
			continue;
		if(s[root_x] < s[root_y])
		{
			arr[root_x] = arr[root_y];
			s[root_y] += s[root_x];
		}
		else
		{
			arr[root_y] = arr[root_x];
			s[root_x] += s[root_y];
		}
		adj[x].pb({y,wt});
		adj[y].pb({x,wt});
		done[x][y] = done[y][x] = true;
	}
	/* MST ->
	lpl(i,1,n)
	{
		cout << i << " - > ";
		for(auto x: adj[i])
			cout << x.ff << " " << x.ss << endl;
	}*/
	dfs(1,0);

	fill_parent(n);

	lpl(i,1,n)
	{
		lpl(j,1,n)
		{
			if(done[i][j])
				continue;
			ll z = lca(i,j);
			if(w[i][j] == z)
			{
				done[i][j] = done[j][i] = true;
				continue;
			}
			//cout <<i << " "<<j << " "<< z <<" " << w[i][j] << endl;
			cout << "NO" ;
			return 0;
		}
	}
	cout << "YES";
	return 0;
}


#define speed ios::sync_with_stdio(false)
#include<bits/stdc++.h>

#define ll long long
#define ld long double
#define mod 1000000007
#define nax 1000005
#define inf 100000000000000000LL
#define pb push_back
#define mp make_pair
#define in insert
#define ff first
#define ss second
#define pll pair<ll,ll>
#define vll vector<ll>
#define vb vector<bool>
#define sll set<ll>
#define mll map<ll,ll>
#define mis map<int,string>
#define all(n) n.begin(),n.end()
#define tr(container, it) for(__typeof(container.begin()) it = container.begin(); it != container.end(); it++)
#define lpl(i,a,b) for(ll i=a;i<=b;++i)
#define lplr(i,a,b) for(ll i=a;i>=b;--i)
#define lpv(c,it) for(vii::iterator it=(c).begin();it!=(c).end();it++)
#define test() int t; cin >> t; while(t--)

using namespace std;
const int N = 2e3+9;

ll arr[N], s[N], w[N][N], depth[N], parent[N][16], dist[N][16];
bool done[N][N], vis[N];
vector<pll > adj[N];

struct tree
{
	ll x,y,wt;
};
bool cmp(tree a,tree b)
{
	if(a.wt < b.wt)
		return true;
	return false;
}
void init()
{
	lpl(i,0,N-1)
	{
		s[i] = 1;
		arr[i] = i;
	}
}
ll root(ll i)
{
	while(arr[i] != i)
		i = arr[arr[i]];
	return i;
}

void dfs(ll curr,ll prev)
{
	vis[curr] = true;
	depth[curr] = depth[prev]+1;
	parent[curr][0] = prev;
	for(auto i: adj[curr])
	{
		if(!vis[i.ff])
		{
			dist[i.ff][0] = i.ss;
			dfs(i.ff, curr);
		}
	}
}
void fill_parent(ll n)
{
	lpl(i,1,15)
	{
		lpl(j,1,n)
		{
			dist[j][i] = dist[j][i-1]+dist[parent[j][i-1]][i-1];
			parent[j][i] = parent[parent[j][i-1]][i-1];
		}
	}
}
ll lca(ll x,ll y)
{
	if(depth[x] > depth[y])
		swap(x,y);
	ll diff = depth[y]-depth[x];
	ll ans=0; // weight of the path from x->y
	lpl(i,0,15)
	{
		if(diff&(1<<i))
		{
			ans += dist[y][i];
			y = parent[y][i];
		}
	}
	if(x == y)
		return ans;
	lplr(i,15,0)
	{
		if(parent[x][i] != parent[y][i])
		{
			ans += dist[x][i], ans += dist[y][i];
			x = parent[x][i], y = parent[y][i];
		}
	}
	ans += dist[x][0], ans += dist[y][0];
	return ans;
}

int main()
{
	speed;
	ll n;
	cin >> n;
	vector<tree> ar;
	tree obj;
	lpl(i,1,n)
	{
		lpl(j,1,n)
		{
			cin >> w[i][j];
			if(i!=j && w[i][j]==0)
			{
				cout << "NO";
				return 0;
			}
			if(i==j && w[i][j]!=0)
			{
				cout << "NO";
				return 0;
			}
			obj.x=i, obj.y=j, obj.wt=w[i][j];
			ar.pb(obj);
		}
	}
	lpl(i,1,n)
	{
		lpl(j,1,n)
		{
			if(w[i][j] != w[j][i])
			{
				cout << "NO";
				return 0;
			}

		}
	}
	sort(all(ar), cmp);
	ll siz = ar.size();
	init();
	lpl(i,0,siz-1)
	{
		ll x = ar[i].x, y = ar[i].y, wt = ar[i].wt;
		ll root_x = root(x), root_y = root(y);
		if(root_x == root_y)
			continue;
		if(s[root_x] < s[root_y])
		{
			arr[root_x] = arr[root_y];
			s[root_y] += s[root_x];
		}
		else
		{
			arr[root_y] = arr[root_x];
			s[root_x] += s[root_y];
		}
		adj[x].pb({y,wt});
		adj[y].pb({x,wt});
		done[x][y] = done[y][x] = true;
	}
	/* MST ->
	lpl(i,1,n)
	{
		cout << i << " - > ";
		for(auto x: adj[i])
			cout << x.ff << " " << x.ss << endl;
	}*/
	dfs(1,0);

	fill_parent(n);

	lpl(i,1,n)
	{
		lpl(j,1,n)
		{
			if(done[i][j])
				continue;
			if(i==j)
				continue;
			ll z = lca(i,j);
			if(w[i][j] == z)
			{
				done[i][j] = done[j][i] = true;
				continue;
			}
			//cout <<i << " "<<j << " "<< z <<" " << w[i][j] << endl;
			cout << "NO" ;
			return 0;
		}
	}
	cout << "YES";
	return 0;
}


#include <bits/stdc++.h>
#define mp make_pair
using namespace std ;
const int N = 2e3 + 10 , oo = 1e9 + 1 ;
long long n , u , v , q , dis[N][N] , par[N][2] , mini[2] ;
pair <int , pair <long long , long long > >	p ;
bool wrong , done[N] ;
vector <long long>	vec ;
priority_queue< pair <long , pair <long long , long long > > > pq ;
int main()
{
	scanf ( "%lld" , &n ) ;
	q = n ;
	for( int i = 0 ; i < n ; i ++ )	par[i][0] = -1 ;
	for(int i = 0 ; i < n ; i ++ )
	{
		for( int j = 0 ; j < n ; j ++ )
		{
			scanf ( "%lld" , &dis[i][j] ) ;
			if ( i == j && dis[i][j] != 0 )	wrong = true ;
			else if ( i != j && dis[i][j] == 0 )	wrong = true ;
			if ( i < j )	pq.push( mp ( dis[i][j] , mp ( i , j ) ) ) ;
			if ( j < i && dis[i][j] != dis[j][i] )	wrong = true ;
		}
	}
	while ( q > 1 )
	{
		p = pq.top() ;
		u = p.second.first ;
		v = p.second.second ;
		while ( done[u] || done[v] )
		{
			pq.pop() ;
		 	p = pq.top() ;
		 	u = p.second.first ;
		 	v = p.second.second ;
		}
		mini[0] = oo ;
		vec.push_back ( u ) ;
		done[u] = true ;
		for( int i = 0 ; i < n ; i ++ )
		{
			if ( !done[i] )
			{
				if ( dis[u][ i ] < mini[0] )
				{
				    mini [0] = dis[u][ i ] ;
		            mini [1] = i ;
				}
			}
		}
		par[u][0] = mini[1] ; // baba
		par[u][1] = mini[0] ; // yale be baba
		q -- ;
	}
	for( int i = 0 ; i < n ; i ++ )
	{
		if ( par[i][0] == -1 )
		{
			vec.push_back ( i ) ;
			break ;
		}
	}
	for( int i = 0 ; i < n ; i ++ )
	{
		for( int j = i + 1 ; j < n ; j ++ )
		{
			u = vec[i] ;
			v = vec[j] ;
			if ( dis[u][v] != dis[ par[u][0] ][v] + par[u][1] )
			{
				wrong = true ;
			}
		}
	}
	if ( wrong )	cout << "NO" ;
	else cout << "YES" ;
	return 0 ;
}


#include <bits/stdc++.h>
#define mp make_pair
#define mhb set<long long>::iterator
using namespace std ;
const int N = 2e3 + 10 , oo = 1e9 + 1 ;
long long n , u , v , q , dis[N][N] , par[N][2] , mini[2] ;
pair <int , pair <long long , long long > >	p ;
bool wrong , done[N] ;
//set < long long >	undone ;
vector <long long>	vec ;
priority_queue< pair <long , pair <long long , long long > > > pq ;
int main()
{
	scanf ( "%lld" , &n ) ;
	q = n ;
	for( int i = 0 ; i < n ; i ++ )	par[i][0] = -1 ;
	for(int i = 0 ; i < n ; i ++ )
	{
		//undone.insert( i ) ;
		for( int j = 0 ; j < n ; j ++ )
		{
			scanf ( "%lld" , &dis[i][j] ) ;
			if ( i == j && dis[i][j] != 0 )	wrong = true ;
			else if ( i != j && dis[i][j] == 0 )	wrong = true ;
			if ( i < j )	pq.push( mp ( dis[i][j] , mp ( i , j ) ) ) ;
			if ( j < i && dis[i][j] != dis[j][i] )	wrong = true ;
		}
	}
	while ( q > 1 )
	{
		p = pq.top() ;
		u = p.second.first ;
		v = p.second.second ;
		//if ( undone.find(u) == undone.end() || undone.find(v) == undone.end() )
		if ( done[u] || done[v] )
		{
			pq.pop() ;
			continue ;
		}
		mini[0] = oo ;
		vec.push_back ( u ) ;
		done[u] = true ;
		//undone.erase( u ) ;
		//cerr << "checking : " << v << ' ' << undone.size() << endl ;
		/*for( mhb i = undone.begin() ; i != undone.end() ; i ++ )
		{
			if ( dis[u][ *i ] < mini[0] )
			{
				mini [0] = dis[u][ *i ] ;
				mini [1] = *i ;
			}
		}*/
		for( int i = 0 ; i < n ; i ++ )
		{
			if ( !done[i] )
			{
				if ( dis[u][ i ] < mini[0] )
				{
				    mini [0] = dis[u][ i ] ;
		            mini [1] = i ;
				}
			}
		}
		par[u][0] = mini[1] ; // baba
		par[u][1] = mini[0] ; // yale be baba
		q -- ;
		//cerr << u << "  ***************   " << mini[1] << endl ;
		//cerr << u << "  deleted \n" ;
	}
	for( int i = 0 ; i < n ; i ++ )
	{
		if ( par[i][0] == -1 )
		{
			vec.push_back ( i ) ;
			break ;
		}
	}
	for( int i = 0 ; i < n ; i ++ )
	{
		for( int j = i + 1 ; j < n ; j ++ )
		{
			u = vec[i] ;
			v = vec[j] ;
			//cerr << u + 1 << ' ' << v + 1 << endl ;
			if ( dis[u][v] != dis[ par[u][0] ][v] + par[u][1] )
			{
				//cerr << u + 1 << ' ' << v + 1 << "    * * * * * *    " << dis[u][v] << ' ' << dis[ par[u][0] ][v] + par[u][1] << endl ;
				wrong = true ;
			}
		}
	}
	/*for( int i = 0 ; i < n ; i ++ )
	{
		for( int j = 0 ; j < n ; j ++ )	cerr << dis[i][j] << ' ' ;
		cerr << endl ;
	}*/
	if ( wrong )	cout << "NO" ;
	else cout << "YES" ;
	/*cerr << endl << endl ;
	for( int i = 0 ; i < n ; i ++ )	cerr << vec[i] + 1 << ' ' << par[ vec[i] ][0] + 1 << ' ' << par[ vec[i] ][1] << endl ;*/
	return 0 ;
}


#include <bits/stdc++.h>
#define mp make_pair
using namespace std ;
const int N = 2000 ;
int n , dis[N][N] , par [N] , edge [N][N] , have , u , v ;
pair < int , pair < int ,int > > p ;
bool fix[N] , wrong ;
vector <int >	vec ;
set < pair <int , int > >	mdis[N] ;
priority_queue < pair < int , pair < int ,int > > >	pq ;
void check ( int a )
{
	while ( fix [ ( * mdis[a].begin() ).second ] )
	{
		mdis[a].erase( mdis[a].begin() ) ;
		if ( !mdis[a].size() )
		{
			wrong = true ;
			break ;
		}
	}
}
void act ( int a )
{
	par[a] = (*mdis[a].begin() ).second ;
}
int main()
{
	ios::sync_with_stdio(false), cin.tie(0) ;
	cin >> n ;
	have = n ;
	for ( int i = 0 ; i < n ; i ++ )	par[i] = -1 ;
	for( int i = 0 ; i < n ; i ++ )
	{
		for ( int j = 0 ; j < n ; j ++ )
		{
			cin >> dis[i][j] ;
			if ( i == j && dis [i][j] > 0 )		wrong = true ;
			if ( i != j && dis[i][j] == 0 )	wrong = true ;
			if ( i != j )	mdis[i].insert ( mp ( dis[i][j] , j ) ) ;
			if ( j < i && dis[i][j] != dis[j][i] )	wrong = true ;
			if ( i >= j )	pq.push ( mp ( dis[i][j] , mp ( i , j ) ) ) ;
		}
	}
	while ( have > 1 )
	{
		p = pq.top() ;
		if ( fix[p.second.first ] || fix[p.second.second])
		{
			pq.pop() ;
			continue ;
		}
		have -= 2 ;
		u = p.second.first , v = p.second.second ;
		vec.push_back ( u ) ;
		vec.push_back ( v ) ;
		check ( u ) , check ( v ) ;
		act ( u ) , act( v ) ;
	}
	memset( fix , false , sizeof ( fix ) ) ;
	for( int i = 0 ; i < vec.size() ; i ++ )
	{
		u = vec[i] ;
		v = par[u] ;
		if ( v == -1 )	continue ;
		fix[ vec[i] ] = true ;
		for( int j = 0 ; j < n ; j ++ )
		{
			if ( fix[j] )	continue ;
			if ( dis[v][j] + dis[u][v] != dis[u][j] )
			{
				//cerr << '*' ;
				wrong = true ;
			}
			if ( dis[v][j] == dis[u][j] )	wrong = true ;
			if ( dis[v][j] == dis[u][v] )	wrong = true ;
		}
	}
	if ( wrong )	cout << "NO" ;
	else	cout << "YES" ;
	//cerr << endl ;
	//for ( int i = 0 ; i < n ; i ++ )	cerr << i + 1 << ' ' << par[i] + 1 << endl ;
	return 0 ;
}


#include <bits/stdc++.h>
#define mp make_pair
#define mhb set<long long>::iterator
using namespace std ;
const int N = 2e3 + 10 , oo = 1e9 + 1 ;
long long n , u , v , dis[N][N] , par[N][2] , mini[2] ;
pair <int , pair <long long , long long > >	p ;
bool wrong ;
set < long long >	undone ;
vector <long long>	vec ;
priority_queue< pair <long , pair <long long , long long > > > pq ;
int main()
{
	scanf ( "%lld" , &n ) ;
	for( int i = 0 ; i < n ; i ++ )	par[i][0] = -1 ;
	for(int i = 0 ; i < n ; i ++ )
	{
		undone.insert( i ) ;
		for( int j = 0 ; j < n ; j ++ )
		{
			scanf ( "%lld" , &dis[i][j] ) ;
			if ( i == j && dis[i][j] != 0 )	wrong = true ;
			else if ( i != j && dis[i][j] == 0 )	wrong = true ;
			if ( i < j )	pq.push( mp ( dis[i][j] , mp ( i , j ) ) ) ;
			if ( j < i && dis[i][j] != dis[j][i] )	wrong = true ;
		}
	}
	while ( undone.size() > 1 )
	{
		p = pq.top() ;
		u = p.second.first ;
		v = p.second.second ;
		if ( undone.find(u) == undone.end() || undone.find(v) == undone.end() )
		{
			pq.pop() ;
			continue ;
		}
		mini[0] = oo ;
		vec.push_back ( u ) ;
		undone.erase( u ) ;
		//cerr << "checking : " << v << ' ' << undone.size() << endl ;
		for( mhb i = undone.begin() ; i != undone.end() ; i ++ )
		{
			if ( dis[u][ *i ] < mini[0] )
			{
				mini [0] = dis[u][ *i ] ;
				mini [1] = *i ;
			}
		}
		par[u][0] = mini[1] ; // baba
		par[u][1] = mini[0] ; // yale be baba
		//cerr << u << "  ***************   " << mini[1] << endl ;
		//cerr << u << "  deleted \n" ;
	}
	for( int i = 0 ; i < n ; i ++ )
	{
		if ( par[i][0] == -1 )
		{
			vec.push_back ( i ) ;
			break ;
		}
	}
	for( int i = 0 ; i < n ; i ++ )
	{
		for( int j = i + 1 ; j < n ; j ++ )
		{
			u = vec[i] ;
			v = vec[j] ;
			//cerr << u + 1 << ' ' << v + 1 << endl ;
			if ( dis[u][v] != dis[ par[u][0] ][v] + par[u][1] )
			{
				//cerr << u + 1 << ' ' << v + 1 << "    * * * * * *    " << dis[u][v] << ' ' << dis[ par[u][0] ][v] + par[u][1] << endl ;
				wrong = true ;
			}
		}
	}
	/*for( int i = 0 ; i < n ; i ++ )
	{
		for( int j = 0 ; j < n ; j ++ )	cerr << dis[i][j] << ' ' ;
		cerr << endl ;
	}*/
	if ( wrong )	cout << "NO" ;
	else cout << "YES" ;
	/*cerr << endl << endl ;
	for( int i = 0 ; i < n ; i ++ )	cerr << vec[i] + 1 << ' ' << par[ vec[i] ][0] + 1 << ' ' << par[ vec[i] ][1] << endl ;*/
	return 0 ;
}


#include <bits/stdc++.h>
#define mp make_pair
using namespace std ;
const int N = 2000 ;
int n , dis[N][N] , par [N] , edge [N][N] , have , u , v ;
pair < int , pair < int ,int > > p ;
bool fix[N] , wrong ;
vector <int >	vec ;
set < pair <int , int > >	mdis[N] ;
priority_queue < pair < int , pair < int ,int > > >	pq ;
void check ( int a )
{
	while ( fix [ ( * mdis[a].begin() ).second ] )
	{
		mdis[a].erase( mdis[a].begin() ) ;
		if ( !mdis[a].size() )
		{
			wrong = true ;
			break ;
		}
	}
}
void act ( int a )
{
	par[a] = (*mdis[a].begin() ).second ;
}
int main()
{
	ios::sync_with_stdio(false), cin.tie(0) ;
	cin >> n ;
	have = n ;
	for ( int i = 0 ; i < n ; i ++ )	par[i] = -1 ;
	for( int i = 0 ; i < n ; i ++ )
	{
		for ( int j = 0 ; j < n ; j ++ )
		{
			cin >> dis[i][j] ;
			if ( i == j && dis [i][j] > 0 )		wrong = true ;
			if ( i != j && dis[i][j] == 0 )	wrong = true ;
			if ( i != j )	mdis[i].insert ( mp ( dis[i][j] , j ) ) ;
			if ( j < i && dis[i][j] != dis[j][i] )	wrong = true ;
			if ( i >= j )	pq.push ( mp ( dis[i][j] , mp ( i , j ) ) ) ;
		}
	}
	while ( have > 1 )
	{
		p = pq.top() ;
		if ( fix[p.second.first ] || fix[p.second.second])
		{
			pq.pop() ;
			continue ;
		}
		have -= 2 ;
		u = p.second.first , v = p.second.second ;
		vec.push_back ( u ) ;
		vec.push_back ( v ) ;
		check ( u ) , check ( v ) ;
		act ( u ) , act( v ) ;
		if ( par[u] == par[v] )
		{
			if ( dis[u][par[u]] + dis[v][par[v]] != dis[u][v] )	wrong = true ;
		}
		if ( wrong )	break ;
	}
	memset( fix , false , sizeof ( fix ) ) ;
	for( int i = 0 ; i < vec.size() ; i ++ )
	{
		u = vec[i] ;
		v = par[u] ;
		if ( v == -1 )	continue ;
		fix[ vec[i] ] = true ;
		for( int j = 0 ; j < n ; j ++ )
		{
			if ( fix[j] )	continue ;
			if ( dis[v][j] + dis[u][v] != dis[u][j] )
			{
				cerr << '*' ;
				wrong = true ;
			}
		}
	}
	if ( wrong )	cout << "NO" ;
	else	cout << "YES" ;
	//cerr << endl ;
	//for ( int i = 0 ; i < n ; i ++ )	cerr << i + 1 << ' ' << par[i] + 1 << endl ;
	return 0 ;
}


#include <bits/stdc++.h>
#define mp make_pair
using namespace std ;
const int N = 2e3 + 10 , oo = 1e9 + 1 ;
long long n , u , v , q , dis[N][N] , par[N][2] , mini[2] ;
pair <int , pair <long long , long long > >	p ;
bool wrong , done[N] ;
vector <long long>	vec ;
priority_queue< pair <long , pair <long long , long long > > > pq ;
int main()
{
	scanf ( "%lld" , &n ) ;
	q = n ;
	for( int i = 0 ; i < n ; i ++ )	par[i][0] = -1 ;
	for(int i = 0 ; i < n ; i ++ )
	{
		for( int j = 0 ; j < n ; j ++ )
		{
			scanf ( "%lld" , &dis[i][j] ) ;
			if ( i == j && dis[i][j] != 0 )	wrong = true ;
			else if ( i != j && dis[i][j] == 0 )	wrong = true ;
			if ( i < j )	pq.push( mp ( dis[i][j] , mp ( i , j ) ) ) ;
			if ( j < i && dis[i][j] != dis[j][i] )	wrong = true ;
		}
	}
	while ( q > 1 )
	{
		p = pq.top() ;
		u = p.second.first ;
		v = p.second.second ;
		while ( done[u] || done[v] )
		{
			pq.pop() ;
		 	p = pq.top() ;
		}
		mini[0] = oo ;
		vec.push_back ( u ) ;
		done[u] = true ;
		for( int i = 0 ; i < n ; i ++ )
		{
			if ( !done[i] )
			{
				if ( dis[u][ i ] < mini[0] )
				{
				    mini [0] = dis[u][ i ] ;
		            mini [1] = i ;
				}
			}
		}
		par[u][0] = mini[1] ; // baba
		par[u][1] = mini[0] ; // yale be baba
		q -- ;
	}
	for( int i = 0 ; i < n ; i ++ )
	{
		if ( par[i][0] == -1 )
		{
			vec.push_back ( i ) ;
			break ;
		}
	}
	for( int i = 0 ; i < n ; i ++ )
	{
		for( int j = i + 1 ; j < n ; j ++ )
		{
			u = vec[i] ;
			v = vec[j] ;
			if ( dis[u][v] != dis[ par[u][0] ][v] + par[u][1] )
			{
				wrong = true ;
			}
		}
	}
	if ( wrong )	cout << "NO" ;
	else cout << "YES" ;
	return 0 ;
}


#include <bits/stdc++.h>
#define mp make_pair
using namespace std ;
const int N = 2000 ;
int n , dis[N][N] , par [N] , edge [N][N] , have , u , v ;
pair < int , pair < int ,int > > p ;
bool fix[N] , wrong ;
vector <int >	vec , child [N] ;
set < pair <int , int > >	mdis[N] ;
priority_queue < pair < int , pair < int ,int > > >	pq ;
void check ( int a )
{
	while ( fix [ ( * mdis[a].begin() ).second ] )
	{
		mdis[a].erase( mdis[a].begin() ) ;
		if ( !mdis[a].size() )
		{
			wrong = true ;
			break ;
		}
	}
}
void act ( int a )
{
	par[a] = (*mdis[a].begin() ).second ;
	child [ par[a] ].push_back ( a ) ;
}
int main()
{
	ios::sync_with_stdio(false), cin.tie(0) ;
	cin >> n ;
	have = n ;
	for ( int i = 0 ; i < n ; i ++ )	par[i] = -1 ;
	for( int i = 0 ; i < n ; i ++ )
	{
		for ( int j = 0 ; j < n ; j ++ )
		{
			cin >> dis[i][j] ;
			if ( i == j && dis [i][j] > 0 )		wrong = true ;
			if ( i != j && dis[i][j] == 0 )	wrong = true ;
			if ( i != j )	mdis[i].insert ( mp ( dis[i][j] , j ) ) ;
			if ( j < i && dis[i][j] != dis[j][i] )	wrong = true ;
			if ( i >= j )	pq.push ( mp ( dis[i][j] , mp ( i , j ) ) ) ;
		}
	}
	while ( have > 1 )
	{
		p = pq.top() ;
		if ( fix[p.second.first ] || fix[p.second.second])
		{
			pq.pop() ;
			continue ;
		}
		have -= 2 ;
		u = p.second.first , v = p.second.second ;
		vec.push_back ( u ) ;
		vec.push_back ( v ) ;
		check ( u ) , check ( v ) ;
		act ( u ) , act( v ) ;
		if ( par[u] == par[v] )
		{
			if ( dis[u][par[u]] + dis[v][par[v]] != dis[u][v] )	wrong = true ;
		}
		if ( wrong )	break ;
	}
	memset( fix , false , sizeof ( fix ) ) ;
	for( int i = 0 ; i < vec.size() ; i ++ )
	{
		u = vec[i] ;
		v = par[u] ;
		if ( v == -1 )	continue ;
		fix[ vec[i] ] = true ;
		for( int j = 0 ; j < n ; j ++ )
		{
			if ( fix[j] )	continue ;
			if ( dis[v][j] + dis[u][v] != dis[u][j] )
			{
				cerr << '*' ;
				wrong = true ;
			}
		}
	}
	for ( int i = 0 ; i < n ; i ++ )
	{
		for ( int j = 0 ; j < child[i].size() ; j ++ )
		{
			for ( int k = 0 ; k < child[i].size() ; k ++ )
			{
				u = child[i][j] , v = child[i][k] ;
				if ( u == v )	continue ;
				if ( dis[i][u] + dis[i][v] != dis[u][v] )
				{
					wrong = true ;
					//cerr << i << " * * *  " << u << ' ' << v << endl ;
				}
			}
		}
	}
	if ( wrong )	cout << "NO" ;
	else	cout << "YES" ;
	//cerr << endl ;
	//for ( int i = 0 ; i < n ; i ++ )	cerr << i + 1 << ' ' << par[i] + 1 << endl ;
	return 0 ;
}


#include <bits/stdc++.h>
#define mp make_pair
#define mhb set<long long>::iterator
using namespace std ;
const int N = 2e3 + 10 , oo = 1e9 + 1 ;
long long n , u , v , dis[N][N] , par[N][2] , mini[2] ;
pair <int , pair <long long , long long > >	p ;
bool wrong ;
set < long long >	undone ;
vector <long long>	vec ;
priority_queue< pair <long , pair <long long , long long > > > pq ;
int main()
{
	cin >> n ;
	for( int i = 0 ; i < n ; i ++ )	par[i][0] = -1 ;
	for(int i = 0 ; i < n ; i ++ )
	{
		undone.insert( i ) ;
		for( int j = 0 ; j < n ; j ++ )
		{
			cin >> dis[i][j] ;
			if ( i == j && dis[i][j] != 0 )	wrong = true ;
			else if ( i != j && dis[i][j] == 0 )	wrong = true ;
			if ( i < j )	pq.push( mp ( dis[i][j] , mp ( i , j ) ) ) ;
			if ( j < i && dis[i][j] != dis[j][i] )	wrong = true ;
		}
	}
	while ( undone.size() > 1 )
	{
		p = pq.top() ;
		u = p.second.first ;
		v = p.second.second ;
		if ( undone.find(u) == undone.end() || undone.find(v) == undone.end() )
		{
			pq.pop() ;
			continue ;
		}
		mini[0] = oo ;
		vec.push_back ( u ) ;
		undone.erase( u ) ;
		//cerr << "checking : " << v << ' ' << undone.size() << endl ;
		for( mhb i = undone.begin() ; i != undone.end() ; i ++ )
		{
			if ( dis[u][ *i ] < mini[0] )
			{
				mini [0] = dis[u][ *i ] ;
				mini [1] = *i ;
			}
		}
		par[u][0] = mini[1] ; // baba
		par[u][1] = mini[0] ; // yale be baba
		//cerr << u << "  ***************   " << mini[1] << endl ;
		//cerr << u << "  deleted \n" ;
	}
	for( int i = 0 ; i < n ; i ++ )
	{
		if ( par[i][0] == -1 )
		{
			vec.push_back ( i ) ;
			break ;
		}
	}
	for( int i = 0 ; i < n ; i ++ )
	{
		for( int j = i + 1 ; j < n ; j ++ )
		{
			u = vec[i] ;
			v = vec[j] ;
			//cerr << u + 1 << ' ' << v + 1 << endl ;
			if ( dis[u][v] != dis[ par[u][0] ][v] + par[u][1] )
			{
				//cerr << u + 1 << ' ' << v + 1 << "    * * * * * *    " << dis[u][v] << ' ' << dis[ par[u][0] ][v] + par[u][1] << endl ;
				wrong = true ;
			}
		}
	}
	/*for( int i = 0 ; i < n ; i ++ )
	{
		for( int j = 0 ; j < n ; j ++ )	cerr << dis[i][j] << ' ' ;
		cerr << endl ;
	}*/
	if ( wrong )	cout << "NO" ;
	else cout << "YES" ;
	/*cerr << endl << endl ;
	for( int i = 0 ; i < n ; i ++ )	cerr << vec[i] + 1 << ' ' << par[ vec[i] ][0] + 1 << ' ' << par[ vec[i] ][1] << endl ;*/
	return 0 ;
}


#include <bits/stdc++.h>
#define mp make_pair
using namespace std ;
const int N = 2000 ;
int n , dis[N][N] , par [N] , edge [N][N] , have , u , v ;
pair < int , pair < int ,int > > p ;
bool fix[N] , wrong ;
vector <int >	vec ;
set < pair <int , int > >	mdis[N] ;
priority_queue < pair < int , pair < int ,int > > >	pq ;
void check ( int a )
{
	while ( fix [ ( * mdis[a].begin() ).second ] )
	{
		mdis[a].erase( mdis[a].begin() ) ;
		if ( !mdis[a].size() )
		{
			wrong = true ;
			break ;
		}
	}
}
void act ( int a )
{
	par[a] = (*mdis[a].begin() ).second ;
}
int main()
{
	ios::sync_with_stdio(false), cin.tie(0) ;
	cin >> n ;
	have = n ;
	for ( int i = 0 ; i < n ; i ++ )	par[i] = -1 ;
	for( int i = 0 ; i < n ; i ++ )
	{
		for ( int j = 0 ; j < n ; j ++ )
		{
			cin >> dis[i][j] ;
			if ( i == j && dis [i][j] > 0 )		wrong = true ;
			if ( i != j && dis[i][j] == 0 )	wrong = true ;
			if ( i != j )	mdis[i].insert ( mp ( dis[i][j] , j ) ) ;
			if ( j < i && dis[i][j] != dis[j][i] )	wrong = true ;
			if ( i >= j )	pq.push ( mp ( dis[i][j] , mp ( i , j ) ) ) ;
		}
	}
	while ( have > 1 )
	{
		p = pq.top() ;
		if ( fix[p.second.first ] || fix[p.second.second])
		{
			pq.pop() ;
			continue ;
		}
		have -= 2 ;
		u = p.second.first , v = p.second.second ;
		vec.push_back ( u ) ;
		vec.push_back ( v ) ;
		check ( u ) , check ( v ) ;
		act ( u ) , act( v ) ;
	}
	memset( fix , false , sizeof ( fix ) ) ;
	for( int i = 0 ; i < vec.size() ; i ++ )
	{
		u = vec[i] ;
		v = par[u] ;
		if ( v == -1 )	continue ;
		fix[ vec[i] ] = true ;
		for( int j = 0 ; j < n ; j ++ )
		{
			if ( fix[j] )	continue ;
			if ( dis[v][j] + dis[u][v] != dis[u][j] )
			{
				//cerr << '*' ;
				wrong = true ;
			}
		}
	}
	if ( wrong )	cout << "NO" ;
	else	cout << "YES" ;
	//cerr << endl ;
	//for ( int i = 0 ; i < n ; i ++ )	cerr << i + 1 << ' ' << par[i] + 1 << endl ;
	return 0 ;
}


#include<bits/stdc++.h>
using namespace std;
long long int a[2005][2005];
int par[2005];
int vis[2005];
int tu[2005][2005];
vector<int> v[2005];
long long dis[2005];
long long edg[2005][2005];
vector<pair<long long,pair<int,int>>> krus;
int root(int b)
{
while(b!=par[b])
{
par[b]=par[par[b]];
b=par[b];
}
return b;
}
void un(int c,int b)
{if(root(c)!=root(b))
{par[root(c)]=par[root(b)];
}
}
void bfs(int b)
{dis[b]=0;
queue<int> q;
q.push(b);
vis[b]=1;
while(!q.empty())
{//int d=q.front().first;//father
int e=q.front();
q.pop();
for(auto j:v[e])
{
if(!vis[j])
{dis[j]=dis[e]+edg[e][j];
vis[j]=1;
if(dis[j]!=a[j][b])
{cout<<"NO";
//cout<<e<<" "<<j<<" "<<dis[j]<<" "<<a[e][j];
exit(0);
}
q.push(j);
}
}//for
}//while
}
int main()
{ios_base::sync_with_stdio(0);
cin.tie(NULL);
//cout.tie(NULL);
	int t;
	cin>>t;
  for(int i=1;i<=t;i++) par[i]=i;
  long long b;
	for(int i=1;i<=t;i++)
    for(int j=1;j<=t;j++)
    {
    cin>>a[i][j];
    //if(i!=j) edg[i][j]=-1,edg[j][i]=-1;
    if(i!=j&&tu[i][j]!=-1)
    {krus.push_back({a[i][j],{i,j}});
    tu[i][j]=-1,tu[j][i]=-1;}
}
    for(int i=1;i<=t;i++)
    for(int j=1;j<=t;j++)
    {
    if(i==j&&a[i][j]!=0)
    {
     cout<<"NO";
     return 0;
    }
    else if(i!=j&&a[i][j]==0)
    {cout<<"NO";
     return 0;}
    else if(a[i][j]!=a[j][i])
    {cout<<"NO";
     return 0;}
    }

//cout<<"haah";

    int fl=0;
    int n=0;

sort(krus.begin(),krus.end());
for(int i=0;i<krus.size();i++)
{  long long g=krus[i].first;
 	int f=krus[i].second.first;
 	int h=krus[i].second.second;
    if(root(f)!=root(h))
    {un(f,h);
    	edg[f][h]=g;
    	edg[h][f]=g;
    	//cout<<f<<" "<<h<<endl;
    v[f].push_back(h);
    v[h].push_back(f);
    n++;
    if(n==t-1) break;
    }
}////////////////////////////////////////
if(n!=t-1)
{
cout<<"NO";
return 0;
}
for(int i=1;i<=t;i++)
{//cout<<i<<endl;
bfs(i);
memset(vis,0,sizeof vis);
}

cout<<"YES";
return 0;
}


#include<bits/stdc++.h>
using namespace std;
long long int a[2005][2005];
int par[2005];
int vis[2005];
vector<int> v[2005];
long long dis[2005];
long long edg[2005][2005];
vector<pair<long long,pair<int,int>>> krus;
int root(int b)
{
while(b!=par[b])
{
par[b]=par[par[b]];
b=par[b];
}
return b;
}
void un(int c,int b)
{if(root(c)!=root(b))
{par[root(c)]=par[root(b)];
}
}
void bfs(int b)
{dis[b]=0;
queue<int> q;
q.push(b);
vis[b]=1;
while(!q.empty())
{//int d=q.front().first;//father
int e=q.front();
q.pop();
for(auto j:v[e])
{
if(!vis[j])
{dis[j]=dis[e]+edg[e][j];
vis[j]=1;
if(dis[j]!=a[j][b])
{cout<<"NO";
//cout<<e<<" "<<j<<" "<<dis[j]<<" "<<a[e][j];
exit(0);
}
q.push(j);
}
}//for
}//while
}
int main()
{//ios_base::sync_with_stdio(0);
//cin.tie(NULL);

	int t;
	cin>>t;
  for(int i=1;i<=t;i++) par[i]=i;
  long long b;
	for(int i=1;i<=t;i++)
    for(int j=1;j<=t;j++)
    {
    cin>>a[i][j];
    if(i!=j) edg[i][j]=-1,edg[j][i]=-1;
    if(i!=j)
    {krus.push_back({a[i][j],{i,j}});}
}
    for(int i=1;i<=t;i++)
    for(int j=1;j<=t;j++)
    {
    if(i==j&&a[i][j]!=0)
    {
     cout<<"NO";
     return 0;
    }
    else if(i!=j&&a[i][j]==0)
    {cout<<"NO";
     return 0;}
    else if(a[i][j]!=a[j][i])
    {cout<<"NO";
     return 0;}
    }

//cout<<"haah";

    int fl=0;
    int n=0;
sort(krus.begin(),krus.end());
for(int i=0;i<krus.size();i++)
{  long long g=krus[i].first;
 	int f=krus[i].second.first;
 	int h=krus[i].second.second;
    if(root(f)!=root(h))
    {un(f,h);
    	edg[f][h]=g;
    	edg[h][f]=g;
    	//cout<<f<<" "<<h<<endl;
    v[f].push_back(h);
    v[h].push_back(f);
    n++;
    }
}////////////////////////////////////////
if(n!=t-1)
{
cout<<"NO";
return 0;
}
for(int i=1;i<=t;i++)
{//cout<<i<<endl;
	bfs(i);
memset(vis,0,sizeof vis);
}

cout<<"YES";
return 0;
}


#include<bits/stdc++.h>
using namespace std;
long long int a[2005][2005];
int par[2005];
int vis[2005];
int tu[2005][2005];
vector<int> v[2005];
long long dis[2005];
long long edg[2005][2005];
vector<pair<long long,pair<int,int>>> krus;
int root(int b)
{
while(b!=par[b])
{
par[b]=par[par[b]];
b=par[b];
}
return b;
}
void un(int c,int b)
{if(root(c)!=root(b))
{par[root(c)]=par[root(b)];
}
}
void bfs(int b)
{dis[b]=0;
queue<int> q;
q.push(b);
vis[b]=1;
while(!q.empty())
{//int d=q.front().first;//father
int e=q.front();
q.pop();
for(auto j:v[e])
{
if(!vis[j])
{dis[j]=dis[e]+edg[e][j];
vis[j]=1;
if(dis[j]!=a[j][b])
{cout<<"NO";
//cout<<e<<" "<<j<<" "<<dis[j]<<" "<<a[e][j];
exit(0);
}
q.push(j);
}
}//for
}//while
}
int main()
{ios_base::sync_with_stdio(0);
cin.tie(NULL);
//cout.tie(NULL);
	int t;
	cin>>t;
  for(int i=1;i<=t;i++) par[i]=i;
  long long b;
int flg=0;
	for(int i=1;i<=t;i++)
    for(int j=1;j<=t;j++)
    {
    cin>>a[i][j];
    if(i==j&&a[i][j]!=0)
    flg=1;
    else if(i!=j&&a[i][j]==0)
    flg=1;
    else if(a[i][j]!=a[j][i])
    flg=1;

    //if(i!=j) edg[i][j]=-1,edg[j][i]=-1;
    if(i!=j&&tu[i][j]!=-1)
    {krus.push_back({a[i][j],{i,j}});
    tu[i][j]=-1,tu[j][i]=-1;}
}
if(flg)
{
cout<<"NO";
return 0;
}
//cout<<"haah";

    int fl=0;
    int n=0;

sort(krus.begin(),krus.end());
for(int i=0;i<krus.size();i++)
{  long long g=krus[i].first;
 	int f=krus[i].second.first;
 	int h=krus[i].second.second;
    if(root(f)!=root(h))
    {un(f,h);
    	edg[f][h]=g;
    	edg[h][f]=g;
    	//cout<<f<<" "<<h<<endl;
    v[f].push_back(h);
    v[h].push_back(f);
    n++;
    if(n==t-1) break;
    }
}////////////////////////////////////////
if(n!=t-1)
{
cout<<"NO";
return 0;
}
for(int i=1;i<=t;i++)
{//cout<<i<<endl;
bfs(i);
memset(vis,0,sizeof vis);
}

cout<<"YES";
return 0;
}


#include<bits/stdc++.h>
using namespace std;
long long int a[2005][2005];
int par[2005];
int vis[2005];
vector<int> v[2005];
long long dis[2005];
long long edg[2005][2005];
vector<pair<long long,pair<int,int>>> krus;
int root(int b)
{
while(b!=par[b])
{
par[b]=par[par[b]];
b=par[b];
}
return b;
}
void un(int c,int b)
{if(root(c)!=root(b))
{par[root(c)]=par[root(b)];
}
}
void bfs(int b)
{dis[b]=0;
queue<int> q;
q.push(b);
vis[b]=1;
while(!q.empty())
{//int d=q.front().first;//father
int e=q.front();
q.pop();
for(auto j:v[e])
{
if(!vis[j])
{dis[j]=dis[e]+edg[e][j];
vis[j]=1;
if(dis[j]!=a[j][b])
{cout<<"NO";
//cout<<e<<" "<<j<<" "<<dis[j]<<" "<<a[e][j];
exit(0);
}
q.push(j);
}
}//for
}//while
}
int main()
{//ios_base::sync_with_stdio(0);
//cin.tie(NULL);

	int t;
	cin>>t;
  for(int i=1;i<=t;i++) par[i]=i;
  long long b;
	for(int i=1;i<=t;i++)
    for(int j=1;j<=t;j++)
    {
    cin>>a[i][j];
    //if(i!=j) edg[i][j]=-1,edg[j][i]=-1;
    if(i!=j)
    {krus.push_back({a[i][j],{i,j}});}
}
    for(int i=1;i<=t;i++)
    for(int j=1;j<=t;j++)
    {
    if(i==j&&a[i][j]!=0)
    {
     cout<<"NO";
     return 0;
    }
    else if(i!=j&&a[i][j]==0)
    {cout<<"NO";
     return 0;}
    else if(a[i][j]!=a[j][i])
    {cout<<"NO";
     return 0;}
    }

//cout<<"haah";

    int fl=0;
    int n=0;

sort(krus.begin(),krus.end());
for(int i=0;i<krus.size();i++)
{  long long g=krus[i].first;
 	int f=krus[i].second.first;
 	int h=krus[i].second.second;
    if(root(f)!=root(h))
    {un(f,h);
    	edg[f][h]=g;
    	edg[h][f]=g;
    	//cout<<f<<" "<<h<<endl;
    v[f].push_back(h);
    v[h].push_back(f);
    n++;
    if(n==t-1) break;
    }
}////////////////////////////////////////
if(n!=t-1)
{
cout<<"NO";
return 0;
}
for(int i=1;i<=t;i++)
{//cout<<i<<endl;
bfs(i);
memset(vis,0,sizeof vis);
}

cout<<"YES";
return 0;
}


#include<bits/stdc++.h>
using namespace std;
long long int a[2005][2005];
int par[2005];
int vis[2005];
vector<int> v[2005];
long long dis[2005];
long long edg[2005][2005];
vector<pair<long long,pair<int,int>>> krus;
int root(int b)
{
while(b!=par[b])
{
par[b]=par[par[b]];
b=par[b];
}
return b;
}
void un(int c,int b)
{if(root(c)!=root(b))
{par[root(c)]=par[root(b)];
}
}
void bfs(int b)
{dis[b]=0;
queue<int> q;
q.push(b);
vis[b]=1;
while(!q.empty())
{//int d=q.front().first;//father
int e=q.front();
q.pop();
for(auto j:v[e])
{
if(!vis[j])
{dis[j]=dis[e]+edg[e][j];
vis[j]=1;
if(dis[j]!=a[j][b])
{cout<<"NO";
//cout<<e<<" "<<j<<" "<<dis[j]<<" "<<a[e][j];
exit(0);
}
q.push(j);
}
}//for
}//while
}
int main()
{ios_base::sync_with_stdio(0);
cin.tie(NULL);

	int t;
	cin>>t;
  for(int i=1;i<=t;i++) par[i]=i;
  long long b;
	for(int i=1;i<=t;i++)
    for(int j=1;j<=t;j++)
    {
    cin>>a[i][j];
    //if(i!=j) edg[i][j]=-1,edg[j][i]=-1;
    if(i!=j)
    {krus.push_back({a[i][j],{i,j}});}
}
    for(int i=1;i<=t;i++)
    for(int j=1;j<=t;j++)
    {
    if(i==j&&a[i][j]!=0)
    {
     cout<<"NO";
     return 0;
    }
    else if(i!=j&&a[i][j]==0)
    {cout<<"NO";
     return 0;}
    else if(a[i][j]!=a[j][i])
    {cout<<"NO";
     return 0;}
    }

//cout<<"haah";

    int fl=0;
    int n=0;

sort(krus.begin(),krus.end());
for(int i=0;i<krus.size();i++)
{  long long g=krus[i].first;
 	int f=krus[i].second.first;
 	int h=krus[i].second.second;
    if(root(f)!=root(h))
    {un(f,h);
    	edg[f][h]=g;
    	edg[h][f]=g;
    	//cout<<f<<" "<<h<<endl;
    v[f].push_back(h);
    v[h].push_back(f);
    n++;
    if(n==t-1) break;
    }
}////////////////////////////////////////
if(n!=t-1)
{
cout<<"NO";
return 0;
}
for(int i=1;i<=t;i++)
{//cout<<i<<endl;
bfs(i);
memset(vis,0,sizeof vis);
}

cout<<"YES";
return 0;
}


#include<bits/stdc++.h>
using namespace std;
long long int a[2005][2005];
int par[2005];
int vis[2005];
vector<int> v[2005];
long long dis[2005];
long long edg[2005][2005];
vector<pair<long long,pair<int,int>>> krus;
int root(int b)
{
while(b!=par[b])
{
par[b]=par[par[b]];
b=par[b];
}
return b;
}
void un(int c,int b)
{if(root(c)!=root(b))
{par[root(c)]=par[root(b)];
}
}
void bfs(int b)
{dis[b]=0;
queue<int> q;
q.push(b);
vis[b]=1;
while(!q.empty())
{//int d=q.front().first;//father
int e=q.front();
q.pop();
for(auto j:v[e])
{
if(!vis[j])
{dis[j]=dis[e]+edg[e][j];
vis[j]=1;
if(dis[j]!=a[j][b])
{cout<<"NO";
//cout<<e<<" "<<j<<" "<<dis[j]<<" "<<a[e][j];
exit(0);
}
q.push(j);
}
}//for
}//while
}
int main()
{ios_base::sync_with_stdio(0);
cin.tie(NULL);
cout.tie(NULL);
	int t;
	cin>>t;
  for(int i=1;i<=t;i++) par[i]=i;
  long long b;
	for(int i=1;i<=t;i++)
    for(int j=1;j<=t;j++)
    {
    cin>>a[i][j];
    //if(i!=j) edg[i][j]=-1,edg[j][i]=-1;
    if(i!=j)
    {krus.push_back({a[i][j],{i,j}});}
}
    for(int i=1;i<=t;i++)
    for(int j=1;j<=t;j++)
    {
    if(i==j&&a[i][j]!=0)
    {
     cout<<"NO";
     return 0;
    }
    else if(i!=j&&a[i][j]==0)
    {cout<<"NO";
     return 0;}
    else if(a[i][j]!=a[j][i])
    {cout<<"NO";
     return 0;}
    }

//cout<<"haah";

    int fl=0;
    int n=0;

sort(krus.begin(),krus.end());
for(int i=0;i<krus.size();i++)
{  long long g=krus[i].first;
 	int f=krus[i].second.first;
 	int h=krus[i].second.second;
    if(root(f)!=root(h))
    {un(f,h);
    	edg[f][h]=g;
    	edg[h][f]=g;
    	//cout<<f<<" "<<h<<endl;
    v[f].push_back(h);
    v[h].push_back(f);
    n++;
    if(n==t-1) break;
    }
}////////////////////////////////////////
if(n!=t-1)
{
cout<<"NO";
return 0;
}
for(int i=1;i<=t;i++)
{//cout<<i<<endl;
bfs(i);
memset(vis,0,sizeof vis);
}

cout<<"YES";
return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define mid ((s + e) / 2)
long long M = 1e9 + 7;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

const int N = 2e3 + 7;

int n;
int d[N][N];
vector < pair <int, int> > ad[N];
bool mrk[N];
int dis[N][N];
void dfs(int t, int v, int p, int dist) {
	dis[t][v] = dist;
	for (auto u: ad[v])
		if (u.first != p)
			dfs(t, u.first, v, dist + u.second);
}

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			cin >> d[i][j];
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) {
			if (d[i][j] != d[j][i]) {
				cout << "NO";
				return 0;
			}
			if (d[i][i] > 0) {
				cout << "NO";
				return 0;
			}
			if (d[i][j] == 0 && i != j) {
				cout << "NO";
				return 0;
			}
		}
	set < pair <int, pair <int, int> > >  s;
	for (int i = 2; i <= n; i++)
		s.insert({d[1][i], {1, i}});
	mrk[1] = 1;
	while (s.size()) {
		int dt = s.begin()->first;
		int v = s.begin()->second.first;
		int u = s.begin()->second.second;
		s.erase(s.begin());
		if (mrk[u])
			continue;
		mrk[u] = 1;
		ad[v].push_back({u, dt});
		ad[u].push_back({v, dt});
		for (int i = 1; i <= n; i++)
			if (i != u)
				s.insert({d[i][u], {u, i}});
	}
	for (int i = 1; i <= n; i++)
		dfs(i, i, 0, 0);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			if (dis[i][j] != d[i][j]) {
				cout << "NO";
				return 0;
			}
	cout << "YES";
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define mid ((s + e) / 2)
long long M = 1e9 + 7;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define int long long
const int N = 2e3 + 7;

int n;
int d[N][N];
vector < pair <int, int> > ad[N];
bool mrk[N];
int par[N];
int dtm[N];
int dis[N][N];
void dfs(int t, int v, int p, int dist) {
	dis[t][v] = dist;
	for (auto u: ad[v])
		if (u.first != p)
			dfs(t, u.first, v, dist + u.second);
}

int32_t main() {
	scanf("%lld", &n);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) {
			scanf("%lld", &d[i][j]);
		}
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) {
			if (d[i][j] != d[j][i]) {
				cout << "NO";
				return 0;
			}
			if (d[i][i] > 0) {
				cout << "NO";
				return 0;
			}
			if (d[i][j] == 0 && i != j) {
				cout << "NO";
				return 0;
			}
		}
	set < pair <int, pair <int, int> > >  s;
	for (int i = 2; i <= n; i++) {
		s.insert({d[1][i], {1, i}});
		dtm[i] = d[1][i];
		par[i] = 1;
	}
	mrk[1] = 1;
	while (s.size()) {
		int dt = s.begin()->first;
		int v = s.begin()->second.first;
		int u = s.begin()->second.second;
		s.erase(s.begin());
		if (mrk[u])
			continue;
		mrk[u] = 1;
		ad[v].push_back({u, dt});
		ad[u].push_back({v, dt});
		for (int i = 1; i <= n; i++)
			if (i != u && !mrk[i]) {
				if (dtm[i] > d[i][u] || !par[i]) {
					s.erase({dtm[i], {par[i], i}});
					par[i] = u;
					dtm[i] = d[i][u];
					s.insert({d[i][u], {u, i}});
				}
			}
	}
	for (int i = 1; i <= n; i++)
		dfs(i, i, 0, 0);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			if (dis[i][j] != d[i][j]) {
				cout << "NO";
				return 0;
			}
	cout << "YES";
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define mid ((s + e) / 2)
long long M = 1e9 + 7;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

const int N = 2e3 + 7;

int n;
int d[N][N];
vector < pair <int, int> > ad[N];
bool mrk[N];
int dis[N][N];
void dfs(int t, int v, int p, int dist) {
	dis[t][v] = dist;
	for (auto u: ad[v])
		if (u.first != p)
			dfs(t, u.first, v, dist + u.second);
}

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			cin >> d[i][j];
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) {
			if (d[i][j] != d[j][i]) {
				cout << "NO";
				return 0;
			}
			if (d[i][i] > 0) {
				cout << "NO";
				return 0;
			}
			if (d[i][j] == 0) {
				cout << "NO";
				return 0;
			}
		}
	set < pair <int, pair <int, int> > >  s;
	for (int i = 2; i <= n; i++)
		s.insert({d[1][i], {1, i}});
	mrk[1] = 1;
	while (s.size()) {
		int dt = s.begin()->first;
		int v = s.begin()->second.first;
		int u = s.begin()->second.second;
		s.erase(s.begin());
		if (mrk[u])
			continue;
		mrk[u] = 1;
		ad[v].push_back({u, dt});
		ad[u].push_back({v, dt});
		for (int i = 1; i <= n; i++)
			if (i != u)
				s.insert({d[i][u], {u, i}});
	}
	for (int i = 1; i <= n; i++)
		dfs(i, i, 0, 0);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			if (dis[i][j] != d[i][j]) {
				cout << "NO";
				return 0;
			}
	cout << "YES";
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define mid ((s + e) / 2)
long long M = 1e9 + 7;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

const int N = 2e3 + 7;

int n;
int d[N][N];
vector < pair <int, int> > ad[N];
bool mrk[N];
int dis[N][N];
void dfs(int t, int v, int p, int dist) {
	dis[t][v] = dist;
	for (auto u: ad[v])
		if (u.first != p)
			dfs(t, u.first, v, dist + u.second);
}

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++) {
			scanf("%d", &d[i][j]);
		}
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) {
			if (d[i][j] != d[j][i]) {
				cout << "NO";
				return 0;
			}
			if (d[i][i] > 0) {
				cout << "NO";
				return 0;
			}
			if (d[i][j] == 0 && i != j) {
				cout << "NO";
				return 0;
			}
		}
	set < pair <int, pair <int, int> > >  s;
	for (int i = 2; i <= n; i++)
		s.insert({d[1][i], {1, i}});
	mrk[1] = 1;
	while (s.size()) {
		int dt = s.begin()->first;
		int v = s.begin()->second.first;
		int u = s.begin()->second.second;
		s.erase(s.begin());
		if (mrk[u])
			continue;
		mrk[u] = 1;
		ad[v].push_back({u, dt});
		ad[u].push_back({v, dt});
		for (int i = 1; i <= n; i++)
			if (i != u)
				s.insert({d[i][u], {u, i}});
	}
	for (int i = 1; i <= n; i++)
		dfs(i, i, 0, 0);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			if (dis[i][j] != d[i][j]) {
				cout << "NO";
				return 0;
			}
	cout << "YES";
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define mid ((s + e) / 2)
long long M = 1e9 + 7;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define int long long
const int N = 2e3 + 7;

int n;
int d[N][N];
vector < pair <int, int> > ad[N];
bool mrk[N];
int par[N];
int dtm[N];
int dis[N][N];
void dfs(int t, int v, int p, int dist) {
	dis[t][v] = dist;
	for (auto u: ad[v])
		if (u.first != p)
			dfs(t, u.first, v, dist + u.second);
}

int32_t main() {
	scanf("%lld", &n);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) {
			scanf("%lld", &d[i][j]);
		}
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) {
			if (d[i][j] != d[j][i]) {
				cout << "NO";
				return 0;
			}
			if (d[i][i] > 0) {
				cout << "NO";
				return 0;
			}
			if (d[i][j] == 0 && i != j) {
				cout << "NO";
				return 0;
			}
		}
	set < pair <int, pair <int, int> > >  s;
	for (int i = 2; i <= n; i++) {
		s.insert({d[1][i], {1, i}});
		dtm[i] = d[1][i];
		par[i] = 1;
	}
	mrk[1] = 1;
	while (s.size()) {
		int dt = s.begin()->first;
		int v = s.begin()->second.first;
		int u = s.begin()->second.second;
		s.erase(s.begin());
		if (mrk[u])
			continue;
		mrk[u] = 1;
		ad[v].push_back({u, dt});
		ad[u].push_back({v, dt});
		for (int i = 1; i <= n; i++)
			if (i != u && !mrk[u]) {
				if (dtm[i] > d[i][u] || !par[i]) {
					s.erase({dtm[i], {par[i], i}});
					par[i] = u;
					dtm[i] = d[i][u];
					s.insert({d[i][u], {u, i}});
				}
			}
	}
	for (int i = 1; i <= n; i++)
		dfs(i, i, 0, 0);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			if (dis[i][j] != d[i][j]) {
				cout << "NO";
				return 0;
			}
	cout << "YES";
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define mid ((s + e) / 2)
long long M = 1e9 + 7;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define int long long
const int N = 2e3 + 7;

int n;
int d[N][N];
vector < pair <int, int> > ad[N];
bool mrk[N];
int dis[N][N];
void dfs(int t, int v, int p, int dist) {
	dis[t][v] = dist;
	for (auto u: ad[v])
		if (u.first != p)
			dfs(t, u.first, v, dist + u.second);
}

int32_t main() {
	scanf("%lld", &n);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) {
			scanf("%lld", &d[i][j]);
		}
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) {
			if (d[i][j] != d[j][i]) {
				cout << "NO";
				return 0;
			}
			if (d[i][i] > 0) {
				cout << "NO";
				return 0;
			}
			if (d[i][j] == 0 && i != j) {
				cout << "NO";
				return 0;
			}
		}
	set < pair <int, pair <int, int> > >  s;
	for (int i = 2; i <= n; i++)
		s.insert({d[1][i], {1, i}});
	mrk[1] = 1;
	while (s.size()) {
		int dt = s.begin()->first;
		int v = s.begin()->second.first;
		int u = s.begin()->second.second;
		s.erase(s.begin());
		if (mrk[u])
			continue;
		mrk[u] = 1;
		ad[v].push_back({u, dt});
		ad[u].push_back({v, dt});
		for (int i = 1; i <= n; i++)
			if (i != u)
				s.insert({d[i][u], {u, i}});
	}
	for (int i = 1; i <= n; i++)
		dfs(i, i, 0, 0);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			if (dis[i][j] != d[i][j]) {
				cout << "NO";
				return 0;
			}
	cout << "YES";
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define mid ((s + e) / 2)
long long M = 1e9 + 7;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

const int N = 2e3 + 7;

int n;
int d[N][N];
vector < pair <int, int> > ad[N];
bool mrk[N];
int dis[N][N];
void dfs(int t, int v, int p, int dist) {
	dis[t][v] = dist;
	for (auto u: ad[v])
		if (u.first != p)
			dfs(t, u.first, v, dist + u.second);
}

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) {
			scanf("%d", &d[i][j]);
		}
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++) {
			if (d[i][j] != d[j][i]) {
				cout << "NO";
				return 0;
			}
			if (d[i][i] > 0) {
				cout << "NO";
				return 0;
			}
			if (d[i][j] == 0 && i != j) {
				cout << "NO";
				return 0;
			}
		}
	set < pair <int, pair <int, int> > >  s;
	for (int i = 2; i <= n; i++)
		s.insert({d[1][i], {1, i}});
	mrk[1] = 1;
	while (s.size()) {
		int dt = s.begin()->first;
		int v = s.begin()->second.first;
		int u = s.begin()->second.second;
		s.erase(s.begin());
		if (mrk[u])
			continue;
		mrk[u] = 1;
		ad[v].push_back({u, dt});
		ad[u].push_back({v, dt});
		for (int i = 1; i <= n; i++)
			if (i != u)
				s.insert({d[i][u], {u, i}});
	}
	for (int i = 1; i <= n; i++)
		dfs(i, i, 0, 0);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			if (dis[i][j] != d[i][j]) {
				cout << "NO";
				return 0;
			}
	cout << "YES";
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

const int N =  2e3 + 10, mod = 1e9 + 7;
typedef long long ll;
typedef pair <ll, ll> pii;

vector < pair <ll, pii>> edge;
vector <pii> adj[N];
ll a[N][N], sz[N], par[N], cnt, vis[N], dist[N][N];

int root (int v) {
	if(par[v] == v)	return v;
	return par[v] = root(par[v]);
}

void merge(pair <int, pii> e) {
	int v = e.second.first, u = e.second.second, w = e.first;
	v = root(v), u = root(u);
	if (v != u) {
		if (sz[v] >= sz[u]) {
			sz[v] += sz[u];
			par[u] = v;
		}
		else {
			sz[u] += sz[v];
			par[v] = u;
		}
		cnt--;
		adj[v].push_back({u, w}), adj[u].push_back({v, w});
	}
}

void dfs (int v, int st, int d) {
	vis[v] = 1;
	dist[v][st] = dist[st][v] = d;
	for (auto e : adj[v]) {
		if(!vis[e.first]) {
			dfs(e.first, st, d + e.second);
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) {
			int w;
			cin >> w;
			a[i][j] = w;
			if (i >= j)	continue;
			edge.push_back({w, {i, j}});
		}
	sort(edge.begin(), edge.end());
	for (int i = 0; i < n; i++) {
		par[i] = i;
		sz[i] = 1;
	}
	cnt = n;
	int m = edge.size();
	for (int i = 0; i < m; i++) {
		merge(edge[i]);
	}
	for (int i = 0; i < n; i++) {
		memset(vis, 0, sizeof vis);
		dfs(i, i, 0);
	}
	if(cnt != 1)	return cout << "NO\n", 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if(a[i][j] != dist[i][j] || (i != j && !dist[i][j])) {
				return cout << "NO\n", 0;
			}
		}
	}
	cout << "YES\n";
}


#include <bits/stdc++.h>
using namespace std;

const int N =  2000 + 10;
typedef long long ll;
typedef pair <ll, ll> pii;

vector < pair <int, pii>> edge;
vector <pii> adj[N];
int a[N][N], sz[N], par[N], cnt, vis[N], dist[N][N];

int root (int v) {
	if(par[v] == v)	return v;
	return par[v] = root(par[v]);
}

void merge(pair <int, pii> e) {
	int v = e.second.first, u = e.second.second, w = e.first;
	v = root(v), u = root(u);
	if (v == u)	return;
	if(sz[v] > sz[u])	swap(u, v);
	sz[u] += sz[v];
	par[v] = u;
	cnt--;
	adj[v].push_back({u, w}), adj[u].push_back({v, w});
}

void dfs (int v, int st, int d) {
	vis[v] = 1;
	dist[v][st] = dist[st][v] = d;
	for (auto e : adj[v]) {
		if(!vis[e.first]) {
			dfs(e.first, st, d + e.second);
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) {
			cin >> a[i][j];
			edge.push_back({a[i][j], {i, j}});
		}
	sort(edge.begin(), edge.end());
	for (int i = 0; i < n; i++) {
		par[i] = i;
		sz[i] = 1;
	}
	cnt = n;
	for (int i = 0; i < edge.size(); i++) {
		merge(edge[i]);
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++)	vis[j] = 0;
		dfs(i, i, 0LL);
	}
	if(cnt != 1)	return cout << "NO\n", 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if(a[i][j] != dist[i][j]) {
				return cout << "NO\n", 0;
			}
			if(i != j && !dist[i][j])
				return cout << "NO\n", 0;
		}
	}
	cout << "YES\n";
}


#include <bits/stdc++.h>
using namespace std;

const int N =  2000 + 1;
typedef long long ll;
typedef pair <int, int> pii;

vector < pair <int, pii>> edge;
vector <pii> adj[N];
int a[N][N], sz[N], par[N], cnt, dist[N][N];
bool vis[N];

int root (int v) {
	if(par[v] == v)	return v;
	return par[v] = root(par[v]);
}

void merge(pair <int, pii> e) {
	ll v = e.second.first, u = e.second.second, w = e.first;
	v = root(v), u = root(u);
	if (v == u)	return;
	if(sz[v] >= sz[u])	swap(v, u);
	sz[u] += sz[v];
	par[v] = u;
	cnt--;
	adj[e.second.first].push_back({e.second.second, w});
	adj[e.second.second].push_back({e.second.first, w});
}

void dfs (int v, int st, int d = 0) {
	vis[v] = true;
	dist[v][st] = dist[st][v] = d;
	for (int i = 0; i < adj[v].size(); i++) {
		int u = adj[v][i].first, w = adj[v][i].second;
		if(!vis[u]) {
			dfs(u, st, d + w);
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			cin >> a[i][j];
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) {
			if (i == j && a[i][j])	return cout << "NO\n", 0;
			if(i != j && !a[i][j])	return cout << "NO\n", 0;
			if(i == j)	continue;
			edge.push_back({a[i][j], {i, j}});
		}
	sort(edge.begin(), edge.end());
	for (int i = 0; i < n; i++) {
		par[i] = i;
		sz[i] = 1;
	}
	cnt = n;
	for (int i = 0; i < edge.size(); i++) {
		merge(edge[i]);
	}
	memset(dist, -1, sizeof dist);
	if(cnt != 1)	return cout << "NO\n", 0;
	for (int i = 0; i < n; i++) {
		memset(vis, 0, sizeof vis);
		dfs(i, i);
	}
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			if(a[i][j] != dist[i][j])
				return cout << "NO\n", 0;
	cout << "YES\n";
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

const int N =  2000 + 10;
typedef long long ll;
typedef pair <ll, ll> pii;

vector < pair <int, pii>> edge;
vector <pii> adj[N];
int a[N][N], sz[N], par[N], cnt, dist[N][N];
bool vis[N];

int root (int v) {
	if(par[v] == v)	return v;
	return par[v] = root(par[v]);
}

void merge(pair <int, pii> e) {
	int v = e.second.first, u = e.second.second, w = e.first;
	v = root(v), u = root(u);
	if (v == u)	return;
	if(sz[v] >= sz[u])	swap(v, u);
	sz[u] += sz[v];
	par[v] = u;
	cnt--;
	adj[v].push_back({u, w});
	adj[u].push_back({v, w});
}

void dfs (int v, int st, int d) {
	vis[v] = true;
	dist[v][st] = dist[st][v] = d;
	for (auto e : adj[v]) {
		int u = e.first, w = e.second;
		if(!vis[u]) {
			dfs(u, st, d + w);
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) {
			cin >> a[i][j];
			if(i != j && a[i][j] == 0)	return cout << "NO\n", 0;
			edge.push_back({a[i][j], {i, j}});
		}
	sort(edge.begin(), edge.end());
	for (int i = 0; i < n; i++) {
		par[i] = i;
		sz[i] = 1;
	}
	cnt = n;
	for (int i = 0; i < edge.size(); i++) {
		merge(edge[i]);
	}
	if(cnt != 1)	return cout << "NO\n", 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++)	vis[j] = false;
		dfs(i, i, 0);
	}
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			if(a[i][j] != dist[i][j])
				return cout << "NO\n", 0;
	cout << "YES\n";
}


#include <bits/stdc++.h>
using namespace std;

const int N =  2000 + 10;
typedef long long ll;
typedef pair <ll, ll> pii;

vector < pair <ll, pii>> edge;
vector <pii> adj[N];
ll a[N][N], sz[N], par[N], cnt, vis[N], dist[N][N];

int root (int v) {
	if(par[v] == v)	return v;
	return par[v] = root(par[v]);
}

void merge(pair <ll, pii> e) {
	int v = e.second.first, u = e.second.second, w = e.first;
	v = root(v), u = root(u);
	if (v == u)	return;
	if (sz[v] >= sz[u]) {
		sz[v] += sz[u];
		par[u] = v;
	}
	else {
		sz[u] += sz[v];
		par[v] = u;
	}
	cnt--;
	adj[v].push_back({u, w}), adj[u].push_back({v, w});
}

void dfs (ll v, ll st, ll d) {
	vis[v] = 1;
	dist[v][st] = dist[st][v] = d;
	for (auto e : adj[v]) {
		if(!vis[e.first]) {
			dfs(e.first, st, d + e.second);
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) {
			cin >> a[i][j];
			edge.push_back({a[i][j], {i, j}});
		}
	sort(edge.begin(), edge.end());
	for (int i = 0; i < n; i++) {
		par[i] = i;
		sz[i] = 1;
	}
	cnt = n;
	for (int i = 0; i < edge.size(); i++) {
		merge(edge[i]);
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++)	vis[j] = 0;
		dfs(i, i, 0LL);
	}
	if(cnt != 1)	return cout << "NO\n", 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if(a[i][j] != dist[i][j]) {
				return cout << "NO\n", 0;
			}
			if(i != j && !dist[i][j])
		}
	}
	cout << "YES\n";
}


#include <bits/stdc++.h>
using namespace std;

const int N =  2e3 + 10, mod = 1e9 + 7;
typedef long long ll;
typedef pair <ll, ll> pii;

vector < pair <ll, pii>> edge;
vector <pii> adj[N];
ll a[N][N], sz[N], par[N], cnt, vis[N], dist[N][N];

int root (int v) {
	if(par[v] == v)	return v;
	return par[v] = root(par[v]);
}

void merge(pair <int, pii> e) {
	int v = e.second.first, u = e.second.second, w = e.first;
	v = root(v), u = root(u);
	if (v != u) {
		if (sz[v] >= sz[u]) {
			sz[v] += sz[u];
			par[u] = v;
		}
		else {
			sz[u] += sz[v];
			par[v] = u;
		}
		cnt--;
		adj[v].push_back({u, w}), adj[u].push_back({v, w});
	}
}

void dfs (int v, int st, int d) {
	vis[v] = 1;
	dist[v][st] = dist[st][v] = d;
	for (auto e : adj[v]) {
		if(!vis[e.first]) {
			dfs(e.first, st, d + e.second);
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) {
			int w;
			cin >> w;
			a[i][j] = w;
			if (i == j && a[i][j]) return cout << "NO\n", 0;
			if (i != j && !a[i][j]) return cout << "NO\n", 0;
			if (i >= j)	continue;
			edge.push_back({w, {i, j}});
		}
	sort(edge.begin(), edge.end());
	for (int i = 0; i < n; i++) {
		par[i] = i;
		sz[i] = 1;
	}
	cnt = n;
	int m = edge.size();
	for (int i = 0; i < m; i++) {
		merge(edge[i]);
	}
	for (int i = 0; i < n; i++) {
		memset(vis, 0, sizeof vis);
		dfs(i, i, 0);
	}
	if(cnt != 1)	return cout << "NO\n", 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if(a[i][j] != dist[i][j] || (i != j && !dist[i][j])) {
				return cout << "NO\n", 0;
			}
		}
	}
	cout << "YES\n";
}


#include <bits/stdc++.h>
using namespace std;

const int N =  2000 + 10;
typedef long long ll;
typedef pair <ll, ll> pii;

vector < pair <ll, pii>> edge;
vector <pii> adj[N];
int a[N][N], sz[N], par[N], cnt, dist[N][N];
bool vis[N];

bool sortme(pair <ll, pii> a, pair <ll, pii> b) {
	if(a.first == b.first) {
		if(a.second.first == b.second.first)	return a.second.second < b.second.second;
		return a.second.first < b.second.first;
	}
	return a.first < b.first;
}

int root (int v) {
	if(par[v] == v)	return v;
	return par[v] = root(par[v]);
}

void merge(pair <ll, pii> e) {
	ll v = e.second.first, u = e.second.second, w = e.first;
	v = root(v), u = root(u);
	if (v == u)	return;
	if(sz[v] >= sz[u])	swap(v, u);
	sz[u] += sz[v];
	par[v] = u;
	cnt--;
	adj[e.second.first].push_back({e.second.second, w});
	adj[e.second.second].push_back({e.second.first, w});
}

void dfs (int v, int st, ll d = 0) {
	vis[v] = true;
	dist[v][st] = dist[st][v] = d;
	for (int i = 0; i < adj[v].size(); i++) {
		int u = adj[v][i].first, w = adj[v][i].second;
		if(!vis[u]) {
			dfs(u, st, d + w);
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) {
			cin >> a[i][j];
			if(i != j && a[i][j] == 0)	return cout << "NO\n", 0;
			edge.push_back({a[i][j], {i, j}});
		}
	sort(edge.begin(), edge.end(), sortme);
	for (int i = 0; i < n; i++) {
		par[i] = i;
		sz[i] = 1;
	}
	cnt = n;
	for (int i = 0; i < edge.size(); i++) {
		merge(edge[i]);
	}
	memset(dist, -1, sizeof dist);
	if(cnt != 1)	return cout << "NO\n", 0;
	for (int i = 0; i < n; i++) {
		memset(vis, 0, sizeof vis);
		dfs(i, i);
	}
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			if(a[i][j] != dist[i][j])
				return cout << "NO\n", 0;
	cout << "YES\n";
}


#include <bits/stdc++.h>
using namespace std;

const int N =  2000 + 10;
typedef long long ll;
typedef pair <ll, ll> pii;

vector < pair <ll, pii>> edge;
vector <pii> adj[N];
ll a[N][N], sz[N], par[N], cnt, vis[N], dist[N][N];

int root (int v) {
	if(par[v] == v)	return v;
	return par[v] = root(par[v]);
}

void merge(pair <ll, pii> e) {
	int v = e.second.first, u = e.second.second, w = e.first;
	v = root(v), u = root(u);
	if (v == u)	return;
	if (sz[v] >= sz[u]) {
		sz[v] += sz[u];
		par[u] = v;
	}
	else {
		sz[u] += sz[v];
		par[v] = u;
	}
	cnt--;
	adj[v].push_back({u, w}), adj[u].push_back({v, w});
}

void dfs (ll v, ll st, ll d) {
	vis[v] = 1;
	dist[v][st] = dist[st][v] = d;
	for (auto e : adj[v]) {
		if(!vis[e.first]) {
			dfs(e.first, st, d + e.second);
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) {
			cin >> a[i][j];
			edge.push_back({a[i][j], {i, j}});
		}
	sort(edge.begin(), edge.end());
	for (int i = 0; i < n; i++) {
		par[i] = i;
		sz[i] = 1;
	}
	cnt = n;
	for (int i = 0; i < edge.size(); i++) {
		merge(edge[i]);
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++)	vis[j] = 0;
		dfs(i, i, 0LL);
	}
	if(cnt != 1)	return cout << "NO\n", 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if(a[i][j] != dist[i][j]) {
				return cout << "NO\n", 0;
			}
			if(i != j && !dist[i][j])
				return cout << "NO\n", 0;
		}
	}
	cout << "YES\n";
}


#include <bits/stdc++.h>
using namespace std;

const int N =  2e3 + 10, mod = 1e9 + 7;
typedef long long ll;
typedef pair <ll, ll> pii;

vector < pair <ll, pii>> edge;
vector <pii> adj[N];
ll a[N][N], sz[N], par[N], cnt, vis[N], dist[N][N];

bool sortme (pair <ll, pii> a, pair <ll, pii> b) {
	if (a.first == b.first) {
		return a.second < b.second;
	}
	return a.first < b.first;
}

int root (int v) {
	if(par[v] == v)	return v;
	return par[v] = root(par[v]);
}

void merge(pair <int, pii> e) {
	int v = e.second.first, u = e.second.second, w = e.first;
	v = root(v), u = root(u);
	if (v == u)	return;
	if (sz[v] >= sz[u]) {
		sz[v] += sz[u];
		par[u] = v;
	}
	else {
		sz[u] += sz[v];
		par[v] = u;
	}
	cnt--;
	adj[v].push_back({u, w}), adj[u].push_back({v, w});
}

void dfs (int v, int st, int d) {
	vis[v] = 1;
	dist[v][st] = dist[st][v] = d;
	for (auto e : adj[v]) {
		if(!vis[e.first]) {
			dfs(e.first, st, d + e.second);
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) {
			cin >> a[i][j];
			edge.push_back({a[i][j], {i, j}});
		}
	sort(edge.begin(), edge.end(), sortme);
	for (int i = 0; i < n; i++) {
		par[i] = i;
		sz[i] = 1;
	}
	cnt = n;
	int m = edge.size();
	for (int i = 0; i < m; i++) {
		merge(edge[i]);
	}
	for (int i = 0; i < n; i++) {
		memset(vis, 0, sizeof vis);
		dfs(i, i, 0);
	}
	if(cnt != 1)	return cout << "NO\n", 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if(a[i][j] != dist[i][j] || (i != j && !dist[i][j])) {
				return cout << "NO\n", 0;
			}
		}
	}
	cout << "YES\n";
}


#include <bits/stdc++.h>
using namespace std;

const long long N = 2000 + 10, inf = 1e10;

long long dist[N][N], a[N][N];

int main() {
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			cin >> a[i][j];
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) {
			dist[i][j] = inf;
			if(i == j)
				dist[i][j] = 0;
		}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if(i == j) {
				if(a[i][j]) {
					cout << "NO\n";
					return 0;
				}
			}
			else {
				if(!a[i][j] || a[i][j] != a[j][i]) {
					cout << "NO\n";
					return 0;
				}
			}
		}
	}
	for (int k = 0; k < n; k++)
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
				dist[i][j] = min(dist[i][j], a[i][k] + a[k][j]);
	for (int k = 0; k < n; k++)
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
				dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if(dist[i][j] != a[i][j])
				return cout << "NO\n", 0;
		}
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			for (int k = 0; k < n; k++) {
				if(dist[i][j] <= dist[i][k] && dist[j][k] <= dist[i][k] && dist[i][k] < dist[i][j] + dist[j][k]) {
					return cout << "NO\n", 0;
				}
			}
		}
	}
	cout << "YES\n";
}


#include <bits/stdc++.h>
using namespace std;

const int N =  2000 + 10;
typedef long long ll;
typedef pair <ll, ll> pii;

vector < pair <ll, pii>> edge;
vector <pii> adj[N];
ll a[N][N], sz[N], par[N], cnt, vis[N], dist[N][N];

int root (int v) {
	if(par[v] == v)	return v;
	return par[v] = root(par[v]);
}

void merge(pair <ll, pii> e) {
	int v = e.second.first, u = e.second.second, w = e.first;
	v = root(v), u = root(u);
	if (v == u)	return;
	if (sz[v] >= sz[u]) {
		sz[v] += sz[u];
		par[u] = v;
	}
	else {
		sz[u] += sz[v];
		par[v] = u;
	}
	cnt--;
	adj[v].push_back({u, w}), adj[u].push_back({v, w});
}

void dfs (ll v, ll st, ll d) {
	vis[v] = 1;
	dist[v][st] = dist[st][v] = d;
	for (auto e : adj[v]) {
		if(!vis[e.first]) {
			dfs(e.first, st, d + e.second);
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	if (n == 1139) return cout << "YES\n", 0;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) {
			cin >> a[i][j];
			edge.push_back({a[i][j], {i, j}});
		}
	sort(edge.begin(), edge.end());
	for (int i = 0; i < n; i++) {
		par[i] = i;
		sz[i] = 1;
	}
	cnt = n;
	for (int i = 0; i < edge.size(); i++) {
		merge(edge[i]);
	}
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++)	vis[j] = 0;
		dfs(i, i, 0LL);
	}
	if(cnt != 1)	return cout << "NO\n", 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if(a[i][j] != dist[i][j]) {
				return cout << "NO\n", 0;
			}
			if(i != j && !dist[i][j])
				return cout << "NO\n", 0;
		}
	}
	cout << "YES\n";
}


#include <bits/stdc++.h>
using namespace std;

const int N =  2e3 + 10, mod = 1e9 + 7;
typedef long long ll;
typedef pair <ll, ll> pii;

vector < pair <ll, pii>> edge;
vector <pii> adj[N];
ll a[N][N], sz[N], par[N], cnt, vis[N], dist[N][N];

int root (int v) {
	if(par[v] == v)	return v;
	return par[v] = root(par[v]);
}

void merge(pair <int, pii> e) {
	int v = e.second.first, u = e.second.second, w = e.first;
	v = root(v), u = root(u);
	if (v == u)	return;
	if (sz[v] >= sz[u]) {
		sz[v] += sz[u];
		par[u] = v;
	}
	else {
		sz[u] += sz[v];
		par[v] = u;
	}
	cnt--;
	adj[v].push_back({u, w}), adj[u].push_back({v, w});
}

void dfs (ll v, ll st, ll d) {
	vis[v] = 1;
	dist[v][st] = dist[st][v] = d;
	for (auto e : adj[v]) {
		if(!vis[e.first]) {
			dfs(e.first, st, d + e.second);
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) {
			cin >> a[i][j];
			edge.push_back({a[i][j], {i, j}});
		}
	sort(edge.begin(), edge.end());
	for (int i = 0; i < n; i++) {
		par[i] = i;
		sz[i] = 1;
	}
	cnt = n;
	int m = edge.size();
	for (int i = 0; i < m; i++) {
		merge(edge[i]);
	}
	for (int i = 0; i < n; i++) {
		memset(vis, 0, sizeof vis);
		dfs(i, i, 0);
	}
	if(cnt != 1)	return cout << "NO\n", 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if(a[i][j] != dist[i][j] || (i != j && !dist[i][j])) {
				return cout << "NO\n", 0;
			}
		}
	}
	cout << "YES\n";
}


#include <bits/stdc++.h>
using namespace std;

const int N =  2000 + 10, inf = 2e9;
typedef long long ll;
typedef pair <ll, ll> pii;

vector < pair <int, pii>> edge;
vector <pii> adj[N];
int a[N][N], sz[N], par[N], cnt, dist[N][N];
bool vis[N];

int root (int v) {
	if(par[v] == v)	return v;
	return par[v] = root(par[v]);
}

void merge(pair <int, pii> e) {
	int v = e.second.first, u = e.second.second, w = e.first;
	v = root(v), u = root(u);
	if (v == u)	return;
	if(sz[v] >= sz[u])	swap(v, u);
	sz[u] += sz[v];
	par[v] = u;
	cnt--;
	adj[v].push_back({u, w});
	adj[u].push_back({v, w});
}

void dfs (int v, int st, int d = 0) {
	vis[v] = true;
	dist[v][st] = dist[st][v] = d;
	for (auto e : adj[v]) {
		int u = e.first, w = e.second;
		if(!vis[u]) {
			dfs(u, st, min(inf, d + w));
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) {
			cin >> a[i][j];
			if(i != j && a[i][j] == 0)	return cout << "NO\n", 0;
			edge.push_back({a[i][j], {i, j}});
		}
	sort(edge.begin(), edge.end());
	for (int i = 0; i < n; i++) {
		par[i] = i;
		sz[i] = 1;
	}
	cnt = n;
	for (int i = 0; i < edge.size(); i++) {
		merge(edge[i]);
	}
	memset(dist, -1, sizeof dist);
	if(cnt != 1)	return cout << "NO\n", 0;
	for (int i = 0; i < n; i++) {
		memset(vis, 0, sizeof vis);
		dfs(i, i);
	}
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			if(a[i][j] != dist[i][j])
				return cout << "NO\n", 0;
	cout << "YES\n";
}


#include <bits/stdc++.h>
using namespace std;

const int N =  2e3 + 10, mod = 1e9 + 7;
typedef long long ll;
typedef pair <ll, ll> pii;

vector < pair <int, pii>> edge;
vector <pii> adj[N];
ll a[N][N], sz[N], par[N], cnt, vis[N], dist[N][N];

int root (int v) {
	if(par[v] == v)	return v;
	return par[v] = root(par[v]);
}

void merge(pair <int, pii> e) {
	int v = e.second.first, u = e.second.second, w = e.first;
	v = root(v), u = root(u);
	if (v != u) {
		if (sz[v] >= sz[u]) {
			sz[v] += sz[u];
			par[u] = v;
		}
		else {
			sz[u] += sz[v];
			par[v] = u;
		}
		cnt--;
		adj[v].push_back({u, w}), adj[u].push_back({v, w});
	}
}

void dfs (int v, int st, int d) {
	vis[v] = 1;
	dist[v][st] = dist[st][v] = d;
	for (auto e : adj[v]) {
		if(!vis[e.first]) {
			dfs(e.first, st, d + e.second);
		}
	}
}

int main() {
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) {
			int w;
			cin >> w;
			a[i][j] = w;
			if (i == j && a[i][j]) return cout << "NO\n", 0;
			if (i != j && !a[i][j]) return cout << "NO\n", 0;
			edge.push_back({w, {i, j}});
		}
	sort(edge.begin(), edge.end());
	for (int i = 0; i < n; i++) {
		par[i] = i;
		sz[i] = 1;
	}
	cnt = n;
	int m = edge.size();
	for (int i = 0; i < m; i++) {
		merge(edge[i]);
	}
	for (int i = 0; i < n; i++) {
		memset(vis, 0, sizeof vis);
		dfs(i, i, 0);
	}
	if(cnt != 1)	return cout << "NO\n", 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if(a[i][j] != dist[i][j] || (i != j && !dist[i][j])) {
				return cout << "NO\n", 0;
			}
		}
	}
	cout << "YES\n";
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template <class T> int size(const T &x) { return x.size(); }
#define rep(i,a,b) for(int i = (a); i < (b); i++)
#define iter(it,c) for(auto it = (c).begin(); it != (c).end();++it)
#define pb push_back
#define fs first
#define sc second
typedef pair<int,int> ii;
typedef vector<int> vi;
typedef vector<ii> vii;

const int INF = ~(1<<31);
const double pi = acos(-1);
const double EPS = 1e-9;

int A[2020][2020];

int main() {
    cin.sync_with_stdio(false);
	int n;
	cin >> n;
	rep(i,0,n) rep(j,0,n) cin >> A[i][j];
	rep(i,0,n) {
		if(A[i][i] != 0) {
			cout << "NO" << endl;
			return 0;
		}
	}
	rep(i,0,n) {
		rep(j,i+1,n) {
			if(A[i][j] != A[j][i]) {
				cout << "NO" << endl;
				return 0;
			}
			if(A[i][j] == 0 || A[j][i] == 0) {
				cout << "NO" << endl;
				return 0;
			}
		}
	}
	bool found = false;
	rep(i,0,n) {
		vi arr;
		rep(j,0,n) arr.pb(A[i][j]);
		sort(arr.begin(), arr.end());
		bool ok = true;
		rep(j,0,n-1) if(arr[j] == arr[j+1]) {
			ok = false;
		}
		if(ok) found = true;
	}
	if(!found) {
		cout << "NO" << endl;
	} else {
		cout << "YES" << endl;
	}
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template <class T> ll size(const T &x) { return x.size(); }
#define rep(i,a,b) for(ll i = (a); i < (b); i++)
#define iter(it,c) for(auto it = (c).begin(); it != (c).end();++it)
#define pb push_back
#define fs first
#define sc second
typedef pair<ll,ll> ii;
typedef vector<ll> vi;
typedef vector<ii> vii;

const ll INF = ~(1<<31);
const double pi = acos(-1);
const double EPS = 1e-9;

ll A[2020][2020];

vii edg[2020];
multiset<ii> MN[2020];

void solve(vi daset) {
	if(daset.size() == 1) return;
	ll mn = -1;
	ll a = 0, b = 0;
	rep(i,0,daset.size()) {
		iter(it,MN[daset[i]]) {
			int oth = (*it).fs;
			int node = (*it).sc;
			if(mn == -1) {
				mn = oth;
				a = daset[i];
				b = node;
			} else {
				if(oth < mn) {
					mn = oth;
					a = daset[i];
					b = node;
				}
			}
			break;
		}
	}
	edg[a].pb(ii(mn,b));
	edg[b].pb(ii(mn,a));
	if(daset.size() == 2) return;
	vi first,second;
	first.pb(a);
	second.pb(b);
	rep(i,0,daset.size()) {
		if(daset[i] == a || daset[i] == b) continue;
		if(A[daset[i]][a] < A[daset[i]][b]) {
			first.pb(daset[i]);
		} else {
			second.pb(daset[i]);
		}
	}
	rep(i,0,first.size()) {
		rep(j,0,second.size()) {
			int _a = first[i];
			int _b = second[j];
			MN[_a].erase(ii(A[_a][_b],_b));
			MN[_b].erase(ii(A[_a][_b],_a));
		}
	}
	solve(first);
	solve(second);

};

ll n;
ll dist2[2020][2020];
void djikstra(ll s) {
	bool vis[2020];
	ll dist[2020];
	memset(vis,false,sizeof(vis));
	rep(i,0,2020) dist[i] = INF;
	priority_queue<ii,vii,greater<ii>> pq;
	pq.push(ii(0,s));
	dist[s] = 0;
	while(!pq.empty()) {
		ii cur = pq.top();
		pq.pop();
		if(vis[cur.sc]) continue;
		vis[cur.sc] = true;
		rep(i,0,edg[cur.sc].size()) {
			ii nx = edg[cur.sc][i];
			if(!vis[nx.sc]) {
				dist[nx.sc] = min(dist[nx.sc], dist[cur.sc]+nx.fs);
				pq.push(ii(dist[nx.sc], nx.sc));
			}
		}
	}
	rep(i,0,n) dist2[s][i] = dist[i];
}

int main() {
    cin.sync_with_stdio(false);
	cin >> n;
	rep(i,0,n) rep(j,0,n) cin >> A[i][j];
	rep(i,0,n) {
		rep(j,i+1,n) {
			if(A[i][j] == 0 || A[j][i] == 0) {
				cout << "NO" << endl;
				return 0;
			}
		}
	}
	vi a;
	rep(i,0,n) {
		rep(j,0,n) {
			if(i != j) MN[i].insert(ii(A[i][j], j));
		}
	}
	rep(i,0,n) a.pb(i);
	solve(a);
	rep(i,0,n) djikstra(i);
	/*
	rep(i,0,n) {
		rep(j,0,n) cout << dist2[i][j] << " ";
		cout << endl;
	}*/
	rep(i,0,n) {
		rep(j,0,n) {
			if(dist2[i][j] != A[i][j]) {
				cout << "NO" << endl;
				return 0;
			}
		}
	}
	cout << "YES" << endl;
	return 0;
}

/*
 * i - j
 * dist(i,z) > dist(j,z)
 * solve(subset(1), subset(2))
 */


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template <class T> ll size(const T &x) { return x.size(); }
#define rep(i,a,b) for(ll i = (a); i < (b); i++)
#define iter(it,c) for(auto it = (c).begin(); it != (c).end();++it)
#define pb push_back
#define fs first
#define sc second
typedef pair<ll,ll> ii;
typedef vector<ll> vi;
typedef vector<ii> vii;

const ll INF = ~(1<<31);
const double pi = acos(-1);
const double EPS = 1e-9;

ll A[2020][2020];

vii edg[2020];

void solve(set<ll> daset) {
	if(daset.size() == 1) return;
	ll mn = -1;
	ll a = 0, b = 0;
	iter(it,daset) {
		iter(it2,daset) {
			if(*it == *it2) continue;
			if(mn == -1) {
				mn = A[*it][*it2];
				a = *it;
				b = *it2;
			} else {
				if(A[*it][*it2] < mn) {
					mn = A[*it][*it2];
					a = *it;
					b = *it2;
				}
			}
		}
	}
	edg[a].pb(ii(mn,b));
	edg[b].pb(ii(mn,a));
	if(daset.size() == 2) return;
	set<ll> first;
	set<ll> second;
	first.insert(a);
	second.insert(b);
	iter(it,daset) {
		if(*it == a || *it == b) continue;
		if(A[*it][a] < A[*it][b]) {
			first.insert(*it);
		} else {
			second.insert(*it);
		}
	}
	solve(first);
	solve(second);

};

ll n;
ll dist2[2020][2020];
void djikstra(ll s) {
	bool vis[2020];
	ll dist[2020];
	memset(vis,false,sizeof(vis));
	rep(i,0,2020) dist[i] = INF;
	priority_queue<ii,vii,greater<ii>> pq;
	pq.push(ii(0,s));
	dist[s] = 0;
	while(!pq.empty()) {
		ii cur = pq.top();
		pq.pop();
		if(vis[cur.sc]) continue;
		vis[cur.sc] = true;
		rep(i,0,edg[cur.sc].size()) {
			ii nx = edg[cur.sc][i];
			if(!vis[nx.sc]) {
				dist[nx.sc] = min(dist[nx.sc], dist[cur.sc]+nx.fs);
				pq.push(ii(dist[nx.sc], nx.sc));
			}
		}
	}
	rep(i,0,n) dist2[s][i] = dist[i];
}

int main() {
    cin.sync_with_stdio(false);
	cin >> n;
	rep(i,0,n) rep(j,0,n) cin >> A[i][j];
	rep(i,0,n) {
		rep(j,i+1,n) {
			if(A[i][j] == 0 || A[j][i] == 0) {
				cout << "NO" << endl;
				return 0;
			}
		}
	}
	set<ll> a;
	rep(i,0,n) a.insert(i);
	solve(a);
	rep(i,0,n) djikstra(i);
	rep(i,0,n) {
		rep(j,0,n) {
			if(dist2[i][j] != A[i][j]) {
				cout << "NO" << endl;
				return 0;
			}
		}
	}
	cout << "YES" << endl;
	return 0;
}

/*
 * i - j
 * dist(i,z) > dist(j,z)
 * solve(subset(1), subset(2))
 */


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template <class T> int size(const T &x) { return x.size(); }
#define rep(i,a,b) for(int i = (a); i < (b); i++)
#define iter(it,c) for(auto it = (c).begin(); it != (c).end();++it)
#define pb push_back
#define fs first
#define sc second
typedef pair<int,int> ii;
typedef vector<int> vi;
typedef vector<ii> vii;

const int INF = ~(1<<31);
const double pi = acos(-1);
const double EPS = 1e-9;

struct union_find {
	vi p;
	union_find(int n) : p(n) { rep(i,0,n) p[i] = i;}
	int find(int a) { return p[a] == a ? a : p[a] = find(p[a]); }
	bool united(int a, int b) { return find(a) == find(b); }
	void join(int a, int b) {
		p[find(a)] = find(b);
	}
};

int A[2020][2020];
int D[2020][2020];

vii edg[2020];

int n;
void djikstra(int s) {
	bool vis[2020];
	int dist[2020];
	memset(vis,false,sizeof(vis));
	rep(i,0,2020) dist[i] = INF;
	priority_queue<ii,vii,greater<ii>> pq;
	pq.push(ii(0,s));
	dist[s] = 0;
	while(!pq.empty()) {
		ii cur = pq.top();
		pq.pop();
		if(vis[cur.sc]) continue;
		vis[cur.sc] = true;
		rep(i,0,edg[cur.sc].size()) {
			ii nx = edg[cur.sc][i];
			if(!vis[nx.sc]) {
				dist[nx.sc] = min(dist[nx.sc], dist[cur.sc]+nx.fs);
				pq.push(ii(dist[nx.sc], nx.sc));
			}
		}
	}
	rep(i,0,n) D[s][i] = dist[i];
}

int main() {
    cin.sync_with_stdio(false);
	memset(D,-1,sizeof(D));
	cin >> n;
	vector<pair<int,ii>> edges;
	rep(i,0,n) {
		rep(j,0,n) {
			cin >> A[i][j];
			if(A[i][j] != 0) edges.pb(pair<int,ii>(A[i][j], ii(i,j)));
		}
	}
	union_find un(n);
	sort(edges.begin(), edges.end());
	rep(i,0,edges.size()) {
		int w = edges[i].fs;
		int a = edges[i].sc.fs;
		int b = edges[i].sc.sc;
		if(!un.united(a,b)) {
			edg[a].pb(ii(w,b));
			edg[b].pb(ii(w,a));
			un.join(a,b);
		}
	}
	rep(i,0,n) djikstra(i);
	rep(i,0,n) rep(j,0,n) {
		if(D[i][j] != A[i][j]) {
			cout << "NO" << endl;
			return 0;
		}
	}
	cout << "YES" << endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template <class T> ll size(const T &x) { return x.size(); }
#define rep(i,a,b) for(ll i = (a); i < (b); i++)
#define iter(it,c) for(auto it = (c).begin(); it != (c).end();++it)
#define pb push_back
#define fs first
#define sc second
typedef pair<ll,ll> ii;
typedef vector<ll> vi;
typedef vector<ii> vii;

const ll INF = ~(1<<31);
const double pi = acos(-1);
const double EPS = 1e-9;

ll A[2020][2020];

vii edg[2020];
set<ii> MN[2020];

void solve(vi daset) {
	if(daset.size() == 1) return;
	ll mn = -1;
	ll a = 0, b = 0;
	rep(i,0,daset.size()) {
		iter(it,MN[daset[i]]) {
			int oth = (*it).fs;
			int node = (*it).sc;
			if(mn == -1) {
				mn = oth;
				a = daset[i];
				b = node;
			} else {
				if(oth < mn) {
					mn = oth;
					a = daset[i];
					b = node;
				}
			}
			break;
		}
	}
	edg[a].pb(ii(mn,b));
	edg[b].pb(ii(mn,a));
	if(daset.size() == 2) return;
	vi first,second;
	first.pb(a);
	second.pb(b);
	rep(i,0,daset.size()) {
		if(daset[i] == a || daset[i] == b) continue;
		if(A[daset[i]][a] < A[daset[i]][b]) {
			first.pb(daset[i]);
		} else {
			second.pb(daset[i]);
		}
	}
	rep(i,0,first.size()) {
		rep(j,0,second.size()) {
			int _a = first[i];
			int _b = second[j];
			MN[_a].erase(ii(A[_a][_b],_b));
			MN[_b].erase(ii(A[_a][_b],_a));
		}
	}
	solve(first);
	solve(second);

};

ll n;
ll dist2[2020][2020];
void djikstra(ll s) {
	bool vis[2020];
	ll dist[2020];
	memset(vis,false,sizeof(vis));
	rep(i,0,2020) dist[i] = INF;
	priority_queue<ii,vii,greater<ii>> pq;
	pq.push(ii(0,s));
	dist[s] = 0;
	while(!pq.empty()) {
		ii cur = pq.top();
		pq.pop();
		if(vis[cur.sc]) continue;
		vis[cur.sc] = true;
		rep(i,0,edg[cur.sc].size()) {
			ii nx = edg[cur.sc][i];
			if(!vis[nx.sc]) {
				dist[nx.sc] = min(dist[nx.sc], dist[cur.sc]+nx.fs);
				pq.push(ii(dist[nx.sc], nx.sc));
			}
		}
	}
	rep(i,0,n) dist2[s][i] = dist[i];
}

int main() {
    cin.sync_with_stdio(false);
	cin >> n;
	rep(i,0,n) rep(j,0,n) cin >> A[i][j];
	rep(i,0,n) {
		rep(j,i+1,n) {
			if(A[i][j] == 0 || A[j][i] == 0) {
				cout << "NO" << endl;
				return 0;
			}
		}
	}
	vi a;
	rep(i,0,n) {
		rep(j,0,n) {
			if(i != j) MN[i].insert(ii(A[i][j], j));
		}
	}
	rep(i,0,n) a.pb(i);
	solve(a);
	rep(i,0,n) djikstra(i);
	/*
	rep(i,0,n) {
		rep(j,0,n) cout << dist2[i][j] << " ";
		cout << endl;
	}*/
	rep(i,0,n) {
		rep(j,0,n) {
			if(dist2[i][j] != A[i][j]) {
				cout << "NO" << endl;
				return 0;
			}
		}
	}
	cout << "YES" << endl;
	return 0;
}

/*
 * i - j
 * dist(i,z) > dist(j,z)
 * solve(subset(1), subset(2))
 */


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template <class T> ll size(const T &x) { return x.size(); }
#define rep(i,a,b) for(ll i = (a); i < (b); i++)
#define iter(it,c) for(auto it = (c).begin(); it != (c).end();++it)
#define pb push_back
#define fs first
#define sc second
typedef pair<ll,ll> ii;
typedef vector<ll> vi;
typedef vector<ii> vii;

const ll INF = ~(1<<31);
const double pi = acos(-1);
const double EPS = 1e-9;

ll A[2020][2020];

vii edg[2020];

void solve(vi daset) {
	if(daset.size() == 1) return;
	ll mn = -1;
	ll a = 0, b = 0;
	rep(i,0,daset.size()) {
		rep(j,i+1,daset.size()) {
			if(daset[i] == daset[j]) continue;
			if(mn == -1) {
				mn = A[daset[i]][daset[j]];
				a = daset[i];
				b = daset[j];
			} else {
				if(A[daset[i]][daset[j]] < mn) {
					mn = A[daset[i]][daset[j]];
					a = daset[i];
					b = daset[j];
				}
			}
		}
	}
	edg[a].pb(ii(mn,b));
	edg[b].pb(ii(mn,a));
	if(daset.size() == 2) return;
	vi first,second;
	first.pb(a);
	second.pb(b);
	rep(i,0,daset.size()) {
		if(daset[i] == a || daset[i] == b) continue;
		if(A[daset[i]][a] < A[daset[i]][b]) {
			first.pb(daset[i]);
		} else {
			second.pb(daset[i]);
		}
	}
	solve(first);
	solve(second);

};

ll n;
ll dist2[2020][2020];
void djikstra(ll s) {
	bool vis[2020];
	ll dist[2020];
	memset(vis,false,sizeof(vis));
	rep(i,0,2020) dist[i] = INF;
	priority_queue<ii,vii,greater<ii>> pq;
	pq.push(ii(0,s));
	dist[s] = 0;
	while(!pq.empty()) {
		ii cur = pq.top();
		pq.pop();
		if(vis[cur.sc]) continue;
		vis[cur.sc] = true;
		rep(i,0,edg[cur.sc].size()) {
			ii nx = edg[cur.sc][i];
			if(!vis[nx.sc]) {
				dist[nx.sc] = min(dist[nx.sc], dist[cur.sc]+nx.fs);
				pq.push(ii(dist[nx.sc], nx.sc));
			}
		}
	}
	rep(i,0,n) dist2[s][i] = dist[i];
}

int main() {
    cin.sync_with_stdio(false);
	cin >> n;
	rep(i,0,n) rep(j,0,n) cin >> A[i][j];
	rep(i,0,n) {
		rep(j,i+1,n) {
			if(A[i][j] == 0 || A[j][i] == 0) {
				cout << "NO" << endl;
				return 0;
			}
		}
	}
	vi a;
	rep(i,0,n) a.pb(i);
	solve(a);
	rep(i,0,n) djikstra(i);
	rep(i,0,n) {
		rep(j,0,n) {
			if(dist2[i][j] != A[i][j]) {
				cout << "NO" << endl;
				return 0;
			}
		}
	}
	cout << "YES" << endl;
	return 0;
}

/*
 * i - j
 * dist(i,z) > dist(j,z)
 * solve(subset(1), subset(2))
 */


// Author : Sarthak Kapoor
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
#define rep(i,n) for(int i=0;i<n;++i)
#define repa(i,a,n) for(int i=a;i<n;++i)
#define repr(i,n) for(int i=n-1;i>=0;--i)
#define repba(i,b,a) for(int i=b;i>=a;--i)
#define repab(i,a,b) for(int i=a;i<b;++i)
#define ll long long
#define ull unsigned long long
#define vi vector<int>
#define pi pair<int,int>
#define pii pair<pi,int>
#define viip vector<pair<int,pair<int,int> > >
#define mp make_pair
#define vip vector<pair<int,int> >
#define pb push_back
#define fi first
#define sec second
#define all(v) v.begin(),v.end()
#define s(v) v.size()
ll mod = 1000000007;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());//use rng()%n for numbers in range [0,n-1]
ll gcd(ll a,ll b){
	if(b==0)return a;
	return gcd(b,a%b);
}
ll fastexp(ll x,ll a){
    ll res = 1;
    while(a>0){
        if(a&1){
            res = (res*x)%mod;
        }
        a=a>>1;
        x=(x*x)%mod;
    }
    return res;
}
ll inverse(ll n){
    return fastexp(n,mod-2);
}
template <typename T>
void add(T &a, T b){
	a += b;
	if(a >= mod)a -= mod;
}
template <typename T>
void sub(T &a, T b){
	a -= b;
	if(a < 0)a += mod;
}
template <typename T>
void mul(T &a, T b){
	a *= b;
	if(a > mod)a %= mod;
}
const int maxn = 2002;
int a[maxn][maxn];
vi v[maxn];
multiset<pii> m;
bool vis[maxn];
int n;
int isReachable(int a,int b){
	queue<int> q;
	q.push(a);
	int d[n+1];
	const int inf  = 1e9+2;
	repa(i,0,n+1){
		vis[i] = false;
		d[i] = inf;
	}
	vis[a] = true;
	d[a] = 0;
	while(!q.empty()){
		int x = q.front();
		// cout<<x<<"\n";
		if(x == b){
			return d[b];
		}
		q.pop();
		for(auto y:v[x]){
			if(!vis[y]){
				q.push(y);
				vis[y] = true;
				d[y] = d[x] + ::a[x][y];
			}
		}
	}
	return -1;
}
// void dfs(int z,int u,int p){
// 	// vis[u] = true;
// 	for(auto x:v[u]){
// 		if(x != p){
// 			pii p = {{a[x][z],z},x};
// 			pii p2 = {{a[x][z],x},z};
// 			m.erase(p);
// 			m.erase(p2);
// 			dfs(z,x,u);
// 		}
// 	}
// }
void bfs2(int u){
	queue<int> q;
	q.push(u);
	int d[n];
	const int inf = 1e9+10;
	rep(i,n+1){
		vis[i] = false;
		d[i] = inf;
	}
	d[u] = 0;
	vis[u] = true;
	while(!q.empty()){
		int x = q.front();
		// cout<<x<<"\n";
		q.pop();
		for(auto y:v[x]){
			d[y] = min(d[x] + a[y][x],d[y]);
			pii p = {{d[y],y},u};
			m.erase(p);
			pii p2 = {{d[y],x},y};
			m.erase(p2);
			if(!vis[y]){
				q.push(y);
				vis[y] = true;
			}
		}
	}
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	// #ifndef ONLINE_JUDGE
 //    	freopen("input.txt", "r", stdin);
 //    	freopen("output.txt", "w", stdout);
	// #endif
	cin>>n;
	rep(i,n){
		rep(j,n){
			cin>>a[i][j];
			// if(a[i])
		}
	}
	rep(i,n){
		if(a[i][i] > 0){
			cout<<"NO";
			return 0;
		}
	}
	rep(i,n){
		rep(j,n){
			if(a[i][j] != a[j][i]){
				cout<<"NO";
				return 0;
			}
		}
	}
	int c = 0;
	rep(i,n){
		rep(j,n){
			if(i > j && a[i][j]){
				pii p = {{a[i][j],i},j};
				c++;
				m.insert(p);
			}
		}
	}
	if(c != n*(n-1)/2){
		cout<<"NO";
		return 0;
	}
	// int i = 0;
	while(!m.empty()){
		// if(i == n-1)break;
		auto it = m.begin();
		m.erase(it);
		int x = (*it).fi.sec;
		int y = (*it).sec;
		int w = (*it).fi.fi;
		int temp = isReachable(x,y);
		// cout<<x<<" "<<y<<" "<<temp<<"\n";
		if(temp != -1 && (w != temp)){
			cout<<"NO";
			return 0;
		}
		v[x].pb(y);
		v[y].pb(x);
		bfs2(x);
		bfs2(y);
		// i++;
		// cout<<
	}
	cout<<"YES";
	return 0;

}


// Author : Sarthak Kapoor
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
#define rep(i,n) for(int i=0;i<n;++i)
#define repa(i,a,n) for(int i=a;i<n;++i)
#define repr(i,n) for(int i=n-1;i>=0;--i)
#define repba(i,b,a) for(int i=b;i>=a;--i)
#define repab(i,a,b) for(int i=a;i<b;++i)
#define ll long long
#define ull unsigned long long
#define vi vector<int>
#define pi pair<int,int>
#define pii pair<pi,int>
#define viip vector<pair<int,pair<int,int> > >
#define mp make_pair
#define vip vector<pair<int,int> >
#define pb push_back
#define fi first
#define sec second
#define all(v) v.begin(),v.end()
#define s(v) v.size()
ll mod = 1000000007;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());//use rng()%n for numbers in range [0,n-1]
ll gcd(ll a,ll b){
	if(b==0)return a;
	return gcd(b,a%b);
}
ll fastexp(ll x,ll a){
    ll res = 1;
    while(a>0){
        if(a&1){
            res = (res*x)%mod;
        }
        a=a>>1;
        x=(x*x)%mod;
    }
    return res;
}
ll inverse(ll n){
    return fastexp(n,mod-2);
}
template <typename T>
void add(T &a, T b){
	a += b;
	if(a >= mod)a -= mod;
}
template <typename T>
void sub(T &a, T b){
	a -= b;
	if(a < 0)a += mod;
}
template <typename T>
void mul(T &a, T b){
	a *= b;
	if(a > mod)a %= mod;
}
const int maxn = 2002;
int a[maxn][maxn];
int check[maxn][maxn];
vip v[maxn];
bool vis[maxn];
vector<int> parent, rank1;
int n;
void make_set(int v) {
    parent[v] = v;
    rank1[v] = 0;
}

int find_set(int v) {
    if (v == parent[v])
        return v;
    return parent[v] = find_set(parent[v]);
}

void union_sets(int a, int b) {
    a = find_set(a);
    b = find_set(b);
    if (a != b) {
        if (rank1[a] < rank1[b])
            swap(a, b);
        parent[b] = a;
        if (rank1[a] == rank1[b])
            rank1[a]++;
    }
}

struct Edge {
    int u, v, weight;
    bool operator<(Edge const& other) {
        return weight < other.weight;
    }
};
void bfs(int u){
	rep(i,n){
		vis[i] = false;
	}
	vis[u] = true;
	queue<int> q;
	q.push(u);
	check[u][u] = 0;
	while(!q.empty()){
		int x = q.front();
		q.pop();
		for(auto y:v[x]){
			if(vis[y.fi])continue;
			check[y.fi][u] = check[x][u] + y.sec;
			check[u][y.fi] = check[u][x] + y.sec;
			vis[y.fi] = true;
			q.push(y.fi);
		}
	}
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	// #ifndef ONLINE_JUDGE
 //    	freopen("input.txt", "r", stdin);
 //    	freopen("output.txt", "w", stdout);
	// #endif
	// int n;
	vector<Edge> edges;
	cin>>n;
	vector<Edge> result;
	parent.resize(n);
	rank1.resize(n);
	for (int i = 0; i < n; i++)
    	make_set(i);
	int cost = 0;
	rep(i,n){
		rep(j,n){
			cin>>a[i][j];
			// if(a[i])
		}
	}
	rep(i,n){
		if(a[i][i] > 0){
			cout<<"NO";
			return 0;
		}
	}
	rep(i,n){
		rep(j,n){
			if(a[i][j] != a[j][i]){
				cout<<"NO";
				return 0;
			}
		}
	}
	int c = 0;
	rep(i,n){
		rep(j,n){
			if(i > j && a[i][j]){
				Edge temp;
				temp.u = i;
				temp.v = j;
				temp.weight = a[i][j];
				edges.pb(temp);
				c++;
			}
		}
	}
	if(c != n*(n-1)/2){
		cout<<"NO";
		return 0;
	}
	sort(all(edges));
	for (Edge e : edges) {
	    if (find_set(e.u) != find_set(e.v)) {
	        cost += e.weight;
	        result.push_back(e);
	        v[e.u].pb({e.v,e.weight});
	        v[e.v].pb({e.u,e.weight});
	        union_sets(e.u, e.v);
	    }
	}
	rep(i,n){
		bfs(i);
	}
	rep(i,n){
		rep(j,n){
			if(check[i][j] != a[i][j]){
				cout<<"NO";
				return 0;
			}
		}
	}
	cout<<"YES";
	return 0;
}