题目来源:LeetCode 997。保留原题图语义,将函数参数与返回值改为标准输入输出。
学习目标
前置知识
先阅读 6.1 图的基本概念。环境需要 Node.js、pnpm 和支持 C++17 的编译器;Make 可选,可用下方 pnpm 命令替代。
题目
小镇有 n 个人。每条信任记录 u v 表示 u 信任 v。若存在一个人不信任任何人,且其余 n-1 人都信任他,则他是法官。请返回法官编号;不存在则输出 -1。信任不是双向关系,也不具有传递性。
输入格式
第一行 n m,随后 m 行为信任记录 u v。
数据范围
1 <= n <= 1000,0 <= m <= 10000,顶点编号 1..n;u != v,每个有序对最多出现一次。
输入为单组有效数据,所有整数和命令按空白分隔。自动评分不包含非法编号、非法命令或违反上述限制的图,不需要额外输出输入校验提示。
输出格式
输出法官编号;不存在时输出 -1。
只向标准输出写入答案;调试信息写入标准错误。按题面规定分行,评分按空白分隔的 token 比较。
样例
样例输入
3 2
1 3
2 3样例输出
31 和 2 都信任 3,3 没有向外的信任记录,因此法官是 3。
实现任务
修改本题目录中的 student/main.cpp,完成 TODO 标记的算法。输入输出骨架可以保留,完整参考实现单独位于 solution/main.cpp。
- 记录每个人直接信任他人的次数和被直接信任的次数。
- 同时检查两个条件,保留不存在法官时的 -1。
正常、边界与错误情况
- 正常情况:按题目定义处理全部输入,输出与输入边的排列顺序无关。
- n=1、m=0:唯一的人满足条件,输出 1。
- n>1、m=0:没有人得到全部信任,输出 -1。
- 常见错误:只看入度会把仍信任别人的人判为法官;相互信任不能合并成无向边。
- 非法输入不在评分范围;不要在标准输出中添加提示词、调试标记或额外解释。
运行与评分
在本 Lab 目录执行:
make doctor
make run
make run CASE=001-sample
make score未安装 Make 时,在仓库根目录执行:
pnpm lab:doctor -- labs/chapter-06/exercise/E-06-05-town-judge
pnpm lab:run -- labs/chapter-06/exercise/E-06-05-town-judge
pnpm lab:run -- labs/chapter-06/exercise/E-06-05-town-judge --case 001-sample
pnpm lab:score -- labs/chapter-06/exercise/E-06-05-town-judge本题有 20 组测试,每组 5 分,总分 100。起始代码可以编译,但尚未实现完整算法;满分需补齐 TODO。作者检查参考解、骨架与预期输出可使用 pnpm lab:verify -- labs/chapter-06/exercise/E-06-05-town-judge。
正确性说明
出度为 0 等价于不信任任何人;在无自环且有序对不重复的条件下,入度为 n-1 等价于其余所有人都信任该人。两个条件同时成立正好与法官定义等价。
复杂度分析
时间 O(n+m),额外空间 O(n);不需要邻接矩阵。
完成清单
思考与复盘
- 为什么“入度减出度等于 n-1”也能判定本题法官?这一判断依赖哪些输入限制?
- 如果允许重复的信任记录,直接统计入度还可靠吗?