codeforces472D
Design Tutorial: Inverse the Problem
给你了一个 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
3
0 2 7
2 0 9
7 9 0
YES
3
1 2 7
2 0 9
7 9 0
NO
3
0 2 2
7 0 9
7 9 0
NO
3
0 1 1
1 0 1
1 1 0
NO
2
0 0
0 0
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=;
bool f=;
char ch=' ';
while(!isdigit(ch))
{
f|=(ch=='-'); ch=getchar();
}
while(isdigit(ch))
{
s=(s<<)+(s<<)+(ch^); ch=getchar();
}
return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
if(x<)
{
putchar('-'); x=-x;
}
if(x<)
{
putchar(x+''); return;
}
write(x/);
putchar((x%)+'');
return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const int N=,M=;
int n,Dis[N][N];
namespace Tree
{
int tot=,Next[M],to[M],val[M],head[N];
int cnt=;
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=;i<=n;i++)
{
Father[i]=i;
for(j=;j<i;j++) E[++cnt]=(Edge){j,i,Dis[j][i]};
}
sort(E+,E+cnt+);
for(i=;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=;i<=n;i++) Root=i,dfs(i,,);
for(i=;i<=n;i++)
{
for(j=;j<=n;j++) if(Path[i][j]!=Dis[i][j])
{
puts("NO"); exit();
}
}
puts("YES");
}
}
int main()
{
int i,j;
R(n);
for(i=;i<=n;i++)
{
for(j=;j<=n;j++) R(Dis[i][j]);
}
for(i=;i<=n;i++)
{
if(Dis[i][i]) return puts("NO"),;
for(j=;j<i;j++) if((Dis[j][i]!=Dis[i][j])||(!Dis[j][i])) return puts("NO"),;
}
Tree::Solve();
return ;
}
/*
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
*/
codeforces472D的更多相关文章
随机推荐
- 如何解决本地mvn编译安装的jar包在IDEA的pom文件中找不到
在IDEA中maven作为一个内置的工具,不需要任何配置就可以使用,点开settings 可以看到有三个maven可以选择 C:/apache-maven-3.5.3这个maven当然是我自己安装的, ...
- groovy函数、字符串、循环
三重单引号字符串 '''a triple single quoted string''' 三重单引号字符串是普通的java.lang.String 三重单引号字符串是多行的.您可以跨越行边界跨越字符串 ...
- NIO与Socket
一.Socket 的使用 1.单线程Socket的使用 /** * 单线程版本 * 问题描述:只能服务单个客户端 * 解决方案:多线程版本 */ public class Socket_V1 { pu ...
- 【零基础学习FreeRTOS嵌入式系统】之一:FreeRTOS环境搭建
[零基础学习FreeRTOS嵌入式系统]之一:FreeRTOS环境搭建 一:FreeRTOS系统下载 在官网上https://www.freertos.org/,找到下载入口. 或直接进入下载地址ht ...
- 【数据库】10.0 MySQL常用语句(一)
显示数据库语句: SHOW DATABASES 只是显示数据库的名字 显示数据库创建语句: SHOW CREATE DATABASE db_name 数据库删除语句: DROP DATABASE ...
- WiFiDog 与 AuthServer
背景 在一些公共场所(比如公交车.地跌.机场等)连接当地的 WiFi 时会弹出一个验证表单,输入验证信息(比如短信验证码)后就能够通过该 WiFi 联网. 本文将介绍通过 OpenWrt WiFiDo ...
- ODP.Net Tips
Overview Oracle Data Provider for .NET是Oracle 提供的.Net版本的数据库连接组件.下载路径. 使用的核心DLL是Oracle.DataAccess.dll ...
- 13.用别名(alias)创建你自己的命令
现在是时候,感受第一次编程经历了!我们将用 alias 命令创建我们自己的命令.但在 开始之前,我们需要展示一个命令行小技巧.可以把多个命令放在同一行上,命令之间 用”;”分开.它像这样工作: com ...
- Python函数汇总(陆续更新中...)
range的用法 函数原型:range(start, end, scan): 参数含义: start:计数从start开始.默认是从0开始.例如range(5)等价于range(0, 5); end: ...
- 【Oracle】DBMS_STATS.GATHER_TABLE_STATS详解
由于Oracle的优化器是CBO,所以对象的统计数据对执行计划的生成至关重要! 作用:DBMS_STATS.GATHER_TABLE_STATS统计表,列,索引的统计信息(默认参数下是对表进行直 ...