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<set>
  9 #include<deque>
 10 #include<stack>
 11 #include<bitset>
 12 #include<algorithm>
 13 #include<functional>
 14 #include<numeric>
 15 #include<utility>
 16 #include<sstream>
 17 #include<iostream>
 18 #include<iomanip>
 19 #include<cstdio>
 20 #include<cmath>
 21 #include<cstdlib>
 22 #include<cstring>
 23 #include<ctime>
 24 #define LL long long
 25 #define maxn 2010
 26 using namespace std;
 27 int n ;
 28 int mi[maxn];
 29 vector <int> mp[2010];
 30 int nmp[maxn][maxn];
 31 int pre[maxn];
 32 bool vis[maxn];
 33
 34 long long  dep[maxn];
 35 void dfs(int la,int zla,int dis)
 36 {
 37    dep[la] = dis;
 38    int len = mp[la].size();
 39    for(int i = 0 ;i < len ;i ++)
 40    {
 41        int ne = mp[la][i];
 42        if(ne != zla)
 43        {
 44           dfs(ne,la,dis + nmp[la][ne]);
 45        }
 46    }
 47 }
 48 void prime()
 49 {
 50     for(int i = 1;i <= n;i ++){
 51        dep[i] = 2e9;
 52        vis[i] = 0 ;
 53     }
 54     dep[1] = 0 ;
 55     while(1)
 56     {
 57        int v = -1;
 58        for(int i = 1;i <= n;i ++)
 59        {
 60           if(!vis[i] && (v == -1 || dep[i] < dep[v]))
 61               v = i ;
 62        }
 63        if(v == -1)
 64            break;
 65        vis[v] = 1;
 66        for(int i = 1;i <= n;i ++)
 67        {
 68            if(!vis[i] && nmp[v][i] < dep[i])
 69            {
 70               dep[i] = nmp[pre[i] = v][i];
 71            }
 72        }
 73     }
 74 }
 75 int main(){
 76      scanf("%d",&n);
 77      int sum = 0 ;
 78      int ok  = 0 ;
 79      for(int i = 1;i <= n;i ++)
 80      {
 81         for(int j = 1;j <= n;j ++)
 82         {
 83             scanf("%d",&nmp[i][j]);
 84         }
 85      }
 86      for(int i = 1;i <= n;i ++)
 87      {
 88         for(int j = 1;j <= n;j ++)
 89         {
 90            if(i!= j && nmp[i][j] == 0 )
 91                ok = 1;
 92            if(nmp[i][j] != nmp[j][i])
 93                ok = 1;
 94         }
 95      }
 96      if(ok)
 97      {
 98        puts("NO");
 99        return 0 ;
100      }
101      prime();
102      for(int i = 2;i <= n;i ++)
103      {
104        mp[i].push_back(pre[i]);
105        mp[pre[i]].push_back(i);
106        //printf("%d %d\n",i,pre[i]);
107      }
108      for(int i = 1;i <= n;i ++)
109      {
110         dfs(i,0,0);
111     /*    for(int j = 1;j <= n;j ++)
112             printf("%lld ",dep[j]);
113         printf("\n");*/
114         for(int j = 1; j <= n;j ++)
115         {
116            if(dep[j] != nmp[i][j])
117            {
118
119               puts("NO");
120               return 0;
121            }
122         }
123      }
124      puts("YES");
125 return 0;
126 }

时间: 2024-10-19 07:32:01

Codeforces 472(#270 ) D Design Tutorial: Inverse the Problem的相关文章

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 Round #270 D Design Tutorial: Inverse the Problem --MST + DFS

题意:给出一个距离矩阵,问是不是一颗正确的带权树. 解法:先按找距离矩阵建一颗最小生成树,因为给出的距离都是最短的点间距离,然后再对每个点跑dfs得出应该的dis[][],再对比dis和原来的mp是否一致即可. 首先还要判断一些东西.具体看代码吧. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #in

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 B. Design Tutorial: Learn from Life

题意:有一个电梯,每一个人都想乘电梯到达自己想要到达的楼层!从a层到b层的时间是|a-b|, 乘客上下电梯的时间忽略不计!问最少需要多少的时间....     这是一道神题啊,自己的思路不知不觉的就按照注解的思路走了,想着用优先队列模拟一下,可能还是没有模拟好吧,一直哇!但是同学的优先队列模拟过了! 没想到是greedy算法简单的几行就解决了! 1 #include<iostream> 2 #include<cmath> 3 #include<cstdio> 4 #in

codeforces C. Design Tutorial: Make It Nondeterministic

题意:每一个人 都有frist name 和 last name! 从每一个人的名字中任意选择 first name 或者 last name 作为这个人的编号!通过对编号的排序,得到每一个人 最终顺序!比较中的序列能否得到给定输出的序列一致! 1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<string> 5 #include<map> 6 #incl