• codeforces472D


    Design Tutorial: Inverse the Problem

     CodeForces - 472D 

    给你了一个 n × n最短距离矩阵。(即矩阵中dis[u][v]为u点到v点的最短距离),判断是否存在一个边权皆为正整数的树,恰好满足这个最短距离矩阵 。

    Input

    第一行为一个整数 n (1 ≤ n ≤ 2000) — 表示图中有多少个点.

    下面 n 行,每行包括 n 个整数 di, j (0 ≤ di, j ≤ 109) — 点i和点j之间的最短距离.

    Output

    如果存在这样的树,输出 "YES", 否则输出"NO".

    Examples

    Input
    3
    0 2 7
    2 0 9
    7 9 0
    Output
    YES
    Input
    3
    1 2 7
    2 0 9
    7 9 0
    Output
    NO
    Input
    3
    0 2 2
    7 0 9
    7 9 0
    Output
    NO
    Input
    3
    0 1 1
    1 0 1
    1 1 0
    Output
    NO
    Input
    2
    0 0
    0 0
    Output
    NO

    sol:首先很明显的性质就是在树上,两个点之间一定有且仅有一条最短的路径,于是很明显用Kruskal把MST构建出来之后暴力dfs判断距离是否相等即可
    Ps:根据样例可以特判掉很多奇奇怪怪的情况,比方说Dis[x][x]!=0或者Dis[x][y]!=Dis[y][x]等等(不过对答案毫无影响)
    #include <bits/stdc++.h>
    using namespace std;
    typedef int ll;
    inline ll read()
    {
        ll s=0;
        bool f=0;
        char ch=' ';
        while(!isdigit(ch))
        {
            f|=(ch=='-'); ch=getchar();
        }
        while(isdigit(ch))
        {
            s=(s<<3)+(s<<1)+(ch^48); ch=getchar();
        }
        return (f)?(-s):(s);
    }
    #define R(x) x=read()
    inline void write(ll x)
    {
        if(x<0)
        {
            putchar('-'); x=-x;
        }
        if(x<10)
        {
            putchar(x+'0'); return;
        }
        write(x/10);
        putchar((x%10)+'0');
        return;
    }
    #define W(x) write(x),putchar(' ')
    #define Wl(x) write(x),putchar('
    ')
    const int N=2005,M=4000005;
    int n,Dis[N][N];
    namespace Tree
    {
        int tot=0,Next[M],to[M],val[M],head[N];
        int cnt=0;
        struct Edge
        {
            int U,V,Quan;
            inline bool operator<(const Edge &tmp)const
            {
                return Quan<tmp.Quan;
            }
        }E[M];
        inline void add(int x,int y,int z)
        {
            Next[++tot]=head[x];
            to[tot]=y;
            val[tot]=z;
            head[x]=tot;
        }
        int Father[N];
        inline int GetFa(int x)
        {
            return (Father[x]==x)?(Father[x]):(Father[x]=GetFa(Father[x]));
        }
        int Root,Path[N][N];
        inline void dfs(int x,int fa,int Sum)
        {
            int i; Path[Root][x]=Sum;
            for(i=head[x];i;i=Next[i]) if(to[i]!=fa)
            {
                dfs(to[i],x,Sum+val[i]);
            }
        }
        inline void Solve()
        {
            int i,j;
            for(i=1;i<=n;i++)
            {
                Father[i]=i;
                for(j=1;j<i;j++) E[++cnt]=(Edge){j,i,Dis[j][i]};
            }
            sort(E+1,E+cnt+1);
            for(i=1;i<=cnt;i++)
            {
                Edge tmp=E[i];
                int x=tmp.U,y=tmp.V,z=tmp.Quan;
                int xx=GetFa(x),yy=GetFa(y);
                if(xx==yy) continue;
                Father[xx]=yy;
                add(x,y,z);
                add(y,x,z);
            }
            for(i=1;i<=n;i++) Root=i,dfs(i,0,0);
            for(i=1;i<=n;i++)
            {
                for(j=1;j<=n;j++) if(Path[i][j]!=Dis[i][j])
                {
                    puts("NO"); exit(0);
                }
            }
            puts("YES");
        }
    }
    int main()
    {
        int i,j;
        R(n);
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++) R(Dis[i][j]);
        }
        for(i=1;i<=n;i++)
        {
            if(Dis[i][i]) return puts("NO"),0;
            for(j=1;j<i;j++) if((Dis[j][i]!=Dis[i][j])||(!Dis[j][i])) return puts("NO"),0;
        }
        Tree::Solve();
        return 0;
    }
    /*
    Input
    3
    0 2 7
    2 0 9
    7 9 0
    Output
    YES
    
    Input
    3
    1 2 7
    2 0 9
    7 9 0
    Output
    NO
    
    Input
    3
    0 2 2
    7 0 9
    7 9 0
    Output
    NO
    
    Input
    3
    0 1 1
    1 0 1
    1 1 0
    Output
    NO
    
    Input
    2
    0 0
    0 0
    Output
    NO
    */
    View Code
     
  • 相关阅读:
    无废话MVC入门教程五[Control与View交互]
    无废话MVC入门教程三[路由设置及视图入门]
    无废话MVC入门教程二[第一个小Demo]
    IDEA 插件开发
    慢慢学Linux驱动开发,第十章,GNU C的扩展
    《UNIX环境高级编程》编译问题彻底解决方案
    GNU make笔记
    outlook2003无法显示地址列表 无法打开与该地址列表的相关"联系人"文件夹解决方案
    慢慢学Linux驱动开发,第十二章,加入内核
    ADS: (Fatal)L6002U:Could not open file:..... & L6002
  • 原文地址:https://www.cnblogs.com/gaojunonly1/p/10793292.html
Copyright © 2020-2023  润新知