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;
}

时间: 2024-08-08 18:50:29

Codeforces Round #270 D Design Tutorial: Inverse the Problem --MST + DFS的相关文章

Codeforces Round #270 D. Design Tutorial: Inverse the Problem

D. Design Tutorial: Inverse the Problem 与u最近的边肯定是与u直接相连的边,所以可以根据这个建树,然后就可以求树上两点之间的距离,判断是否全部匹配. 1 #define bug(x) cout<<#x<<" is "<<x<<endl; 2 #define IO std::ios::sync_with_stdio(0); 3 #include <bits/stdc++.h> 4 #def

Codeforces 472(#270 ) D Design Tutorial: Inverse the Problem

题意:给你一棵数的距离矩阵,问你这个矩阵是否合法 解题思路:利用树的性质进行prime 和连边,产生最小生成树,最后看最小生成树是否和给出的一致就行 解题代码: 1 // File Name: d.cpp 2 // Author: darkdream 3 // Created Time: 2014年09月29日 星期一 00时45分45秒 4 5 #include<vector> 6 #include<list> 7 #include<map> 8 #include&l

codeforces D. Design Tutorial: Inverse the Problem

题意:给定一个矩阵,表示每两个节点之间的权值距离,问是否可以对应生成一棵树, 使得这棵树中的任意两点之间的距离和矩阵中的对应两点的距离相等! 思路:我们将给定的矩阵看成是一个图,a 到 b会有多条路径, 如果存在一棵树,那么 这个树中a->b的距离一定是这个图中所有a->b中路径长度最短的一条!所以我们根据边权, 建立一棵MST树!再将MST树中的任意两点之间的距离求出来,看是否和矩阵中的对应的节点 对距离相同! 1 #include<iostream> 2 #include<

【CF】270D Design Tutorial: Inverse the Problem

题意异常的简单.就是给定一个邻接矩阵,让你判定是否为树.算法1:O(n^3).思路就是找到树边,原理是LCA.判断树边的数目是否为n-1.39-th个数据T了,自己测试2000跑到4s.算法2:O(n^2).思考由图如何得到树,显然MST是可行的.因此,题目变为直接找到MST.然后通过树边构建目标矩阵.判定矩阵是否相等. 1 /* 472D */ 2 #include <iostream> 3 #include <string> 4 #include <map> 5 #

Codeforces Round #270(活用prim算法)

D. Design Tutorial: Inverse the Problem time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output There is an easy way to obtain a new task from an old one called "Inverse the problem": we give

Codeforces Round #270 solution

A.Design Tutorial: Learn from Math 题意:给你一个大于12小于1e6的数,让你把这个数表示为两个合数之和. 解法:筛素数后枚举一个合数判断另一个是否是合数. 代码: 1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <map> 5 #include <string> 6 #include <set> 7 #in

Codeforces Round #270

Codeforces Round #270 题目链接 A:我是筛了下素数.事实上偶数仅仅要输出4和x - 4,奇数输出9和x - 9就可以 B:贪心的策略,把时间排序后.取每k个的位置 C:贪心.每次遇到一个人尽量让他用字典序小的,假设不行就大的,假设还是不行就是矛盾了 D:先推断原来矩阵的对角线.和是否是对称矩阵,求出最小生成树后.dfs n次求出每两点之间的距离.然后你和原来的矩阵相比就能够了 代码: A: #include <cstdio> #include <cstring>

Codeforces Round #270 A B C

ADesign Tutorial: Learn from Math 素数筛 #include<bits/stdc++.h> using namespace std; const int N = 1e6 + 100; int a[N]={0}; int main(){ int n; cin >> n; a[1] = 1; for(int i = 2; i*i <= n; i++){ if(a[i] == 0){ for(int j = i*i; j <= n; j +=

Codeforces Round #270 D C B A

谈论最激烈的莫过于D题了! 看过的两种做法不得不ORZ,特别第二种,简直神一样!!!!! 1th:构造最小生成树. 我们提取所有的边出来按边排序,因为每次我们知道边的权值>0, 之后每次把边加入集合中,不断构造,类似  kruskal算法,构造出边后 再对每个点进行整张图的DFS求距离 复杂度O(N^2lgN):对所有边排序的复杂度. 1 #include<bits/stdc++.h> 2 3 #define N 2222 4 using namespace std; 5 typedef