#P6830. [IOI2020] 连接擎天树

    ID: 5870 远端评测题 1000ms 1024MiB 尝试: 0 已通过: 0 难度: 5 上传者: 标签>2020IOI交互题Special Judge深度优先搜索,DFS

[IOI2020] 连接擎天树

题目背景

这是一道交互题。

本题仅支持 C++ 系列语言,提交时不需要包含 supertrees.h 头文件,但需要在程序开头包含 vector 头文件以及声明函数 void build(std::vector<std::vector<int> > b);

题目描述

滨海湾花园是新加坡的一个大型自然公园。公园内有 nn 个塔,称之为“擎天树”。这些塔的编号为 00n1n-1。我们希望建立一个桥的集合(桥的数目大于等于 00)。每⼀座桥连接两个不同的塔,而且可以双向通行。没有两座桥连接相同的一对塔。

一条从塔 xx 到塔 yy 的路径是一个满足以下条件的塔序列(塔的数目大于等于 11):

  • 序列的第一个元素是 xx
  • 序列的最后一个元素是 yy
  • 序列中所有元素互不相同,

序列中每两个相邻元素(塔)都是被某一座桥连接起来的。

注意根据定义,一个塔到它自己有且仅有一条路径,并且从塔 ii 到塔 jj 的不同路径的数目和从塔 jj 到塔 ii 的不同路径的数目是一样的。

负责该项设计的首席设计师希望待建造的桥梁要符合:任意给定 0i,jn10 \le i,j \le n-1,恰好有 p[i][j]p[i][j] 条从塔 ii 到塔 jj 的不同路径,其中 0p[i][j]30 \le p[i][j] \le 3

请构造一个桥的集合来满足设计师的要求,或判定这样的桥梁集合不可能存在。

实现细节

你需要实现下面的这个函数:

int construct(std::vector<std::vector<int> > p)
  • pp:⼀个表示设计师要求的 n×nn \times n 数组。
  • 如果这个建设方案是存在的,该函数应该恰好调用一次 build(见下文)来给出建设方案,然后应返回 11
  • 否则,该函数应该返回 00,并且不要调用 build
  • 该函数将被调用恰好一次。

函数 build 定义如下:

void build(std::vector<std::vector<int> > b)
  • bb:一个 n×nn \times n 的数组,b[i][j]=1b[i][j]=1 表示有一座桥连接塔 ii 和塔 jj,否则 b[i][j]=0b[i][j]=0
  • 注意该数组必须满足:对所有 0i,jn10 \le i,j \le n-1b[i][j]=b[j][i]b[i][j]=b[j][i];并且对所有 0in10 \le i \le n-1b[i][i]=0b[i][i]=0

提示

样例说明

例 1

考虑以下调用:

construct([[1, 1, 2, 2], [1, 1, 2, 2], [2, 2, 1, 2], [2, 2, 2, 1]])

这表明从塔 00 到塔 11 恰好有一条路径。对于所有其他的塔对 (x,y)(0x<y3)(x,y)(0 \le x<y \le 3), 恰好有两条不同的路径连接塔 xx 和塔 yy。这可以通过建设 44 座桥来实现:连接塔对 (0,1),(1,2),(1,3)(0, 1), (1, 2), (1, 3)(2,3)(2,3)

为了给出这个解决方案,函数 construct 应该做以下调用:

build([[0, 1, 0, 0], [1, 0, 1, 1], [0, 1, 0, 1], [0, 1, 1, 0]])

函数应该返回 11

对于这个例子,存在多种不同的建设方案来满足要求,所有这些方案都被认为是正确的。

例 2

考虑以下调用:

construct([[1, 0], [0, 1]])

这表明无法在两个塔之间进行旅行。这只能通过不建设桥梁来满足。

因此,函数 construct 应该做以下调用:

build([[0, 0], [0, 0]])

然后,函数 construct 应该返回 11

例 3

考虑以下调用:

construct([[1, 3], [3, 1]])

这表明从塔 00 到塔 11 恰好有 33 条路径。这些要求无法满足。因此,函数 construct 应该返回 00 并且不要调用 build

约束条件

  • 1n10001\le n\le 1000
  • p[i][i]=1p[i][i]=1(对所有 0in10 \le i \le n-1
  • p[i][j]=p[j][i]p[i][j]=p[j][i](对所有 0i,jn10 \le i,j \le n-1
  • 0p[i][j]30 \le p[i][j] \le 3(对所有 0i,jn10 \le i,j \le n-1

子任务

  1. (11 分)p[i][j]=1p[i][j]=1(对所有 0i,jn10 \le i,j \le n-1
  2. (10 分)p[i][j]{0,1}p[i][j] \in \{0,1\}(对所有 0i,jn10 \le i,j \le n-1
  3. (19 分)p[i][j]{0,2}p[i][j] \in \{0,2\}(对所有 ij,0i,jn1i \ne j,0 \le i,j \le n-1
  4. (35 分)0p[i][j]20 \le p[i][j]\le 2(对所有 0i,jn10 \le i,j \le n-1)并且至少有一种建设方案满足要求
  5. (21 分)0p[i][j]20 \le p[i][j] \le 2(对所有 0i,jn10 \le i,j \le n-1
  6. (4 分)没有额外约束条件

评测程序示例

评测程序示例以如下格式读取输入数据:

11 行:nn
2+i2+i 行(0in+10 \le i \le n+1):p[i][0] p[i][1]  p[i][n]p[i][0]\ p[i][1]\ \ldots\ p[i][n]

评测程序示例的输出格式如下:

11 行: construct 的返回值。

如果 construct 的返回值为 11,评测程序示例会额外打印:

2+i2+i 行(0in+10 \le i \le n+1):b[i][0] b[i][1]  b[i][n]b[i][0]\ b[i][1]\ \ldots\ b[i][n]