题目来源:洛谷 T471612。原题“图的存储 (邻接矩阵)”要求输出矩阵和邻接表。本 Lab 保留矩阵输出,增加相邻查询,省略邻接表输出,并允许空图。
学习目标
前置知识
先阅读 6.2 图的存储结构。环境需要 Node.js、pnpm 和支持 C++17 的编译器;Make 可选,可用下方 pnpm 命令替代。
题目
给定简单无向图,先输出它的邻接矩阵,再回答 q 次查询:u 与 v 之间是否存在一条直接连接的边?相邻只指直接有边,不等于通过其他顶点可达。
输入格式
第一行 n m q;随后 m 行为无向边 u v;最后 q 行为查询 u v。
数据范围
1 <= n <= 1000,0 <= m <= min(100000,n(n-1)/2),0 <= q <= 100000。顶点编号 1..n,图无自环重边;查询允许 u=v。
输入为单组有效数据,所有整数和命令按空白分隔。自动评分不包含非法编号、非法命令或违反上述限制的图,不需要额外输出输入校验提示。
输出格式
先输出 n 行,每行 n 个 0/1,行列按顶点 1..n 排列。然后输出 q 行,每行是对应查询的结果:有边为 1,无边为 0。
只向标准输出写入答案;调试信息写入标准错误。按题面规定分行,评分按空白分隔的 token 比较。
样例
样例输入
3 2 4
1 2
2 3
1 2
1 3
2 2
2 1样例输出
0 1 0
1 0 1
0 1 0
1
0
0
11 与 2 直接相邻,但 1 与 3 仅能经 2 到达。查询 1 3 的结果是 0,反向查询 2 1 的结果是 1。
实现任务
修改本题目录中的 student/main.cpp,完成 TODO 标记的算法。输入输出骨架可以保留,完整参考实现单独位于 solution/main.cpp。
- 将矩阵初始化为 0,每条无向边更新两个对称单元。
- 按行输出矩阵,再直接索引矩阵回答查询。
正常、边界与错误情况
- 正常情况:按题目定义处理全部输入,输出与输入边的排列顺序无关。
- m=0:矩阵全为 0。
- 查询同一顶点:无自环图的结果为 0。
- q=0:仅输出矩阵。
- 常见错误:不要把路径可达性当相邻关系;输入从 1 开始而数组可能从 0 开始。
- 非法输入不在评分范围;不要在标准输出中添加提示词、调试标记或额外解释。
运行与评分
在本 Lab 目录执行:
make doctor
make run
make run CASE=001-sample
make score未安装 Make 时,在仓库根目录执行:
pnpm lab:doctor -- labs/chapter-06/exercise/E-06-06-adjacency-matrix-queries
pnpm lab:run -- labs/chapter-06/exercise/E-06-06-adjacency-matrix-queries
pnpm lab:run -- labs/chapter-06/exercise/E-06-06-adjacency-matrix-queries --case 001-sample
pnpm lab:score -- labs/chapter-06/exercise/E-06-06-adjacency-matrix-queries本题有 20 组测试,每组 5 分,总分 100。起始代码可以编译,但尚未实现完整算法;满分需补齐 TODO。作者检查参考解、骨架与预期输出可使用 pnpm lab:verify -- labs/chapter-06/exercise/E-06-06-adjacency-matrix-queries。
正确性说明
初始化时没有边,所有单元为 0。每次读入 {u,v},仅将 A[u][v] 和 A[v][u] 置 1,因此读完后单元为 1 当且仅当对应边存在。查询正是读取这个定义。
复杂度分析
时间 O(n^2+m+q),空间 O(n^2);其中矩阵输出本身就需要 O(n^2) 时间,每次查询 O(1)。
完成清单
思考与复盘
- 为什么 n 很大但 m 很小时不适合分配矩阵?
- 有向图的建图语句与这里有什么区别?