https://ac.nowcoder.com/acm/contest/3007/I
每次取剩下的边中距离最短的边
若两点没有连接,则连上这条边
这就是kruskal算法构造最小生成树的过程
基于此判断距离表是否自洽
因为如果表自洽的话,与该城市距离最近的城市一定是直接相连的
#include<queue> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define N 501 typedef long long LL; struct node { int x,y,d; }e[N*N]; int fa[N],g[N][N]; long long f[N][N]; int edge[N]; int find(int i) { return fa[i]==i ? i : fa[i]=find(fa[i]); } void read(int &x) { x=0; char c; c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } bool cmp(node p,node q) { return p.d<q.d; } int main() { int n,m=0,x,sum=0; read(n); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) { read(x); g[i][j]=x; if(i!=j) { e[++m].d=x; e[m].x=i; e[m].y=j; } } sort(e+1,e+m+1,cmp); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) if(i==j) f[i][j]=0; else f[i][j]=1e13; for(int i=1;i<=n;++i) fa[i]=i; int u,v; for(int i=1;i<=m;++i) { u=e[i].x; v=e[i].y; if(find(u)!=find(v)) { f[u][v]=f[v][u]=e[i].d; edge[++sum]=e[i].d; fa[fa[u]]=fa[v]; } } for(int k=1;k<=n;++k) for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) f[i][j]=min(f[i][j],f[i][k]+f[k][j]); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) if(f[i][j]!=g[i][j]) { printf("No"); return 0; } printf("Yes "); sort(edge+1,edge+n); for(int i=1;i<n;++i) printf("%d ",edge[i]); }