这题真的没有问题吗?
rt,求调。缩小数组就会在更小的点M掉。
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#define ll long long
#define _it set<node>::iterator
#define N 2000005
#define frac pair<ll,ll>
using namespace std;
inline int read(){
int f=1,s=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+(ch-'0'),ch=getchar();
return s*f;
}
int M[2005][2005],dis[2005][2005];
int n,m,x,y,flag;
int to[N],from[N],cnt,net[N],V[N],fa[N],tag[N];
struct Edge{
int x,y,z;
}edge[3000005];
void add(int x,int y,int z){
net[++cnt]=from[x];
to[cnt]=y;
V[cnt]=z;
from[x]=cnt;
}
void dfs(int now,int fa,int cur){
for(int i=from[now];i;i=net[i]) {
if(to[i]!=fa) {
dis[cur][to[i]]=dis[cur][now]+V[i];
dfs(to[i],now,cur);
}
}
}
bool cmp(Edge a,Edge b){
return a.z<b.z;
}
int find(int x){
if(fa[x]==x) return x;
else return fa[x]=find(fa[x]);
}
int main(){
n=read();
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
x=read();
flag+=x;
if(i==j) if(x!=0) {puts("NO");return 0;}
else if(M[i][j]!=x) {puts("NO");return 0;}
if(i==j) continue;
if(i>=j) continue;
M[i][j]=M[j][i]=x;
edge[++cnt]=(Edge){i,j,x};
//add(i,j,x),add(j,i,x);
}
fa[i]=i;
}
if(!flag&&n!=1) {puts("NO");return 0;}
for(int i=1;i<=n;i++) if(M[i][i]) {puts("NO");return 0;}
sort(edge+1,edge+cnt+1,cmp);
for(int i=1;i<=cnt;i++){
x=find(edge[i].x),y=find(edge[i].y);
if(x==y) continue;
add(edge[i].x,edge[i].y,edge[i].z);
add(edge[i].y,edge[i].x,edge[i].z);
fa[x]=y;
tag[i]=1;
}
for(int i=1;i<=n;i++) dfs(i,0,i);
for(int i=1;i<=cnt;i++){
if(tag[i]) continue;
x=edge[i].x,y=edge[i].y;
if(dis[x][y]!=M[x][y]){
cout<<"NO\n";
return 0;
}
}
cout<<"YES\n";
return 0;
}