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 an output of the original task, and ask to generate an input, such that solution to the original problem will produce the output we provided. The hard task of Topcoder
Open 2014 Round 2C, InverseRMQ, is a good example.

Now let‘s create a task this way. We will use the task: you are given a tree, please calculate the distance between any pair of its nodes. Yes, it is very easy, but the inverse version is a bit harder: you are given an n?×?n distance
matrix. Determine if it is the distance matrix of a weighted tree (all weights must be positive integers).

Input

The first line contains an integer n (1?≤?n?≤?2000)
— the number of nodes in that graph.

Then next n lines each contains n integers di,?j (0?≤?di,?j?≤?109)
— the distance between node i and node j.

Output

If there exists such a tree, output "YES", otherwise output "NO".

Sample test(s)

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

Note

In the first example, the required tree exists. It has one edge between nodes 1 and 2 with weight 2, another edge between nodes 1 and 3 with weight 7.

In the second example, it is impossible because d1,?1 should
be 0, but it is 1.

In the third example, it is impossible because d1,?2 should
equal d2,?1.

这题给出两个点的距离,问你可以不可以由这些点组成一棵树,我们首先构造一个最小生成树,然后比较各各点之间的距离是否与题目给出的距离相等,可以用dfs搜索整张图的每两个点之间的距离.下面给的做法非dfs做的,用一个数组f[][],记录x,y两点之间的距离,算距离的时候是通过目前点的前驱找,也就是说需要一个数组记录前驱,这样就可以不用dfs了,直接可以算.看完代码就明白了.....

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 2010;
const int INF = 0x3f3f3f3f;
int graph[maxn][maxn];
int prior[maxn];
int visit[maxn];
int dis[maxn];
int f[maxn][maxn];
int n;
bool check()
{
    for(int i = 0; i < n; i++)
    {
        dis[i] = INF;
        if(graph[i][i] != 0) return false;
        for(int j = i+1 ; j < n; j++)
        {
            if(graph[i][j] != graph[j][i] || graph[i][j] == 0) return false;
        }
    }

    memset(visit,0,sizeof(visit));
    memset(prior,-1,sizeof(prior));
    memset(f,0,sizeof(f));
    int cent = n;
    dis[0]=0;
    while(cent--)//循环n次是因为要初始化
    {

        int min = -1;
        for(int i = 0; i < n; i++)
        {
            if(!visit[i] && (min == -1 || dis[i] < dis[min]))
            {
                min = i;
            }
        }
        for(int i = 0; i < n; i++)//在prim算法里面增加这层循环里面的内容算距离
        {
            if(visit[i])//必须是已经访问过的点,才能算距离
            {
                f[i][min] = f[min][i] = f[i][prior[min]] + dis[min];
            }
        }
        visit[min] = true;
        for(int i = 0; i < n; i++)
        {
            if(dis[i] > graph[min][i] )
            {
                dis[i] = graph[min][i];
                prior[i] = min;//记录前驱
            }
        }
    }

    for(int i = 0; i < n; i++)
    {
        for(int j = 0 ; j < n; j++)
        {
            if(f[i][j] != graph[i][j])
            {
                return false;
            }
        }
    }
      return true;
}
int main()
{
#ifdef xxz
    freopen("in","r",stdin);
#endif // xxz
    while(cin>>n)
    {
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
            {
                cin>>graph[i][j];
            }

        if(check()) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}
时间: 2024-08-24 15:18:04

Codeforces Round #270(活用prim算法)的相关文章

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

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 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 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 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 #286 (Div. 2) B. Mr. Kitayuta&#39;s Colorful Graph +foyd算法的应用

B. Mr. Kitayuta's Colorful Graph time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Mr. Kitayuta has just bought an undirected graph consisting of n vertices and m edges. The vertices of the g

codeforces Round 286# problem A. Mr. Kitayuta&#39;s Gift

Mr. Kitayuta has kindly given you a string s consisting of lowercase English letters. You are asked to insert exactly one lowercase English letter into s to make it a palindrome. A palindrome is a string that reads the same forward and backward. For

Codeforces Round #279 (Div. 2) ABCD

Codeforces Round #279 (Div. 2) 做得我都变绿了! Problems # Name     A Team Olympiad standard input/output 1 s, 256 MB  x2377 B Queue standard input/output 2 s, 256 MB  x1250 C Hacking Cypher standard input/output 1 s, 256 MB  x740 D Chocolate standard input/