题解:给边赋上权值,然后求最大生成树,如果不符合那就无解
证明:留坑
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxN=1009; const int maxM=300009; const int oo=1000000000; int TT; int n,m; int f[maxN][maxN]; struct Edge{ int u,v,ed; }edges[maxM]; bool mycmp(const Edge &E1,const Edge &E2){ return E1.ed>E2.ed; } int father[maxN]; int Getf(int x){ if(father[x]==x)return x; return father[x]=Getf(father[x]); } void Unionn(int x,int y){ int fx=Getf(x); int fy=Getf(y); if(fx!=fy){ father[fx]=fy; } } int cntedge=0; int head[maxN]={0}; int to[maxN<<1],nex[maxN<<1],dist[maxN<<1]; void Addedge(int x,int y,int z){ nex[++cntedge]=head[x]; to[cntedge]=y; dist[cntedge]=z; head[x]=cntedge; } int fdist[maxN]; void Dfs(int x,int fa){ for(int i=head[x];i;i=nex[i]){ if(to[i]==fa)continue; fdist[to[i]]=min(fdist[x],dist[i]); Dfs(to[i],x); } } void Myinit(){ cntedge=0; memset(head,0,sizeof(head)); } int rd(){ int r=0,k=1; char c=getchar(); for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1; for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0'; return r*k; } int main(){ scanf("%d",&TT); for(int t=1;t<=TT;++t){ Myinit(); scanf("%d%d",&n,&m); for(int i=1;i<=m;++i)scanf("%d%d",&edges[i].u,&edges[i].v); for(int i=1;i<=n;++i){ for(int j=1;j<=n;++j){ scanf("%d",&f[i][j]); } } for(int i=1;i<=m;++i){ int u=edges[i].u; int v=edges[i].v; edges[i].ed=f[u][v]; } sort(edges+1,edges+1+m,mycmp); for(int i=1;i<=n;++i)father[i]=i; for(int i=1;i<=m;++i){ int u=edges[i].u,v=edges[i].v,z=edges[i].ed; if(Getf(u)==Getf(v))continue; Unionn(u,v); Addedge(u,v,z); Addedge(v,u,z); } int fla=1; for(int u=1;u<=n;++u){ fdist[u]=oo; Dfs(u,0); for(int v=1;v<=n;++v){ if(u==v)continue; if(Getf(u)!=Getf(v)){ if(f[u][v]!=-1){ fla=0;break; } }else{ if(f[u][v]!=fdist[v]){ fla=0;break; } } } if(!fla)break; } if(fla)printf("Case #%d: Yes ",t); else printf("Case #%d: No ",t); } return 0; }