2020牛客寒假算法基础集训营6 I 导航系统

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]);
}
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/12359201.html