Codeforces Round #270 D Design Tutorial: Inverse the Problem --MST + DFS

题意:给出一个距离矩阵,问是不是一颗正确的带权树。

解法:先按找距离矩阵建一颗最小生成树,因为给出的距离都是最短的点间距离,然后再对每个点跑dfs得出应该的dis[][],再对比dis和原来的mp是否一致即可。

首先还要判断一些东西。具体看代码吧。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
#define N 2007

struct Edge
{
    int u,v,w;
}edge[N*N];
int a[N][N],fa[N],dis[N][N];
vector<pair<int,int> > G[N];
int cmp(Edge ka,Edge kb) { return ka.w < kb.w; }
int findset(int x)
{
    if(x != fa[x])
        fa[x] = findset(fa[x]);
    return fa[x];
}

void dfs(int u,int fa,int ori)
{
    for(int i=0;i<G[u].size();i++)
    {
        int v = G[u][i].first;
        if(v == fa) continue;
        dis[ori][v] = dis[ori][u] + G[u][i].second;
        dfs(v,u,ori);
    }
}

int main()
{
    int n,i,j;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
                scanf("%I64d",&a[i][j]);
        int tag = 1;
        for(i=1;i<=n;i++)
        {
            fa[i] = i;
            for(j=1;j<=n;j++)
            {
                if((i == j && a[i][j] != 0)||(i != j && a[i][j] == 0)||(a[i][j] != a[j][i]))
                {
                    tag = 0;
                    break;
                }
            }
            if(!tag) break;
        }
        if(!tag) { puts("NO"); continue; }
        int tot = 0;
        for(i=1;i<=n;i++)
            for(j=i+1;j<=n;j++)
                edge[tot].u = i, edge[tot].v = j,edge[tot++].w = a[i][j];
        sort(edge,edge+tot,cmp);
        for(i=0;i<tot;i++)
        {
            int u = edge[i].u, v = edge[i].v, w = edge[i].w;
            int fx = findset(u), fy = findset(v);
            if(fx != fy)
            {
                G[u].push_back(make_pair(v,w));
                G[v].push_back(make_pair(u,w));
                fa[fx] = fy;
            }
        }
        for(i=1;i<=n;i++)
        {
            dis[i][i] = 0;
            dfs(i,0,i);
            for(j=1;j<=n;j++)
            {
                if(a[i][j] != dis[i][j])
                {
                    tag = 0;
                    break;
                }
            }
            if(!tag) break;
        }
        if(!tag)
            puts("NO");
        else
            puts("YES");
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/whatbeg/p/4000031.html