题目来源:改编自 LeetCode 1042:不邻接植花。原题使用函数接口、从
1开始的花园编号,并接受任意合法方案;本 Lab 改为标准输入输出、从0开始的编号,并规定确定性的选花顺序,方便自动评分。
学习目标
前置知识
开始前先阅读 6.2 图的存储结构中的邻接表部分。你只需要理解无向边、邻接表和顶点的度,不需要使用 DFS、BFS 或回溯。运行 make doctor 可以检查 C++17 编译环境。
题目
有 n 个花园和 m 条双向路径。你需要在每个花园中种下四种花之一,使任意两个通过路径直接相连的花园所种花的种类不同。
输入保证每个花园最多连接三条路径,因此总能找到合法方案。为了让标准输出唯一,必须遵守以下规则:
- 按花园编号
0,1,...,n-1的顺序处理; - 处理花园
u时,查看已经选好花种的邻居; - 从花种
1、2、3、4中选择没有被这些邻居使用的最小编号。
为什么不需要回溯?
花园 u 最多只有三个邻居,因此处理它时,邻居至多占用三种花。四种花中至少有一种没有被占用。以后处理尚未选花的邻居时,它们又会避开 u 已经选择的花,因此无需撤销或重新选择。
输入格式
第一行包含两个整数 n m,分别表示花园数量和双向路径数量。花园编号为 0 到 n-1。
接下来 m 行,每行包含两个整数 u v,表示花园 u 与花园 v 之间有一条双向路径。输入保证:
1 <= n <= 10000;0 <= m <= 20000;0 <= u, v < n;u != v;- 不包含重复路径;
- 每个花园的度不超过
3; - 图可以不连通,也可以包含孤立花园。
输出格式
输出一行 n 个整数。对于 0 <= i < n,从左到右第 i + 1 个整数表示花园 i 选择的花种编号。整数之间用单个空格分隔,行末不添加多余空格。
输出必须满足:
- 每个花种编号都在
1到4之间; - 每条路径的两个端点选择不同花种;
- 结果符合“按花园编号升序处理,并选择最小可用花种”的确定性规则。
样例输入
3 3
0 1
1 2
2 0样例输出
1 2 3花园 0 没有已选花的邻居,因此选择 1;花园 1 避开花园 0 的 1,选择 2;花园 2 同时避开 1 和 2,选择 3。
任务
- 创建包含
n个邻接列表的图; - 对每条路径
(u,v),分别执行graph[u].push_back(v)和graph[v].push_back(u); - 创建长度为
n、初值为0的颜色数组,其中0表示尚未选花; - 按
0到n-1的顺序处理花园; - 枚举当前花园的邻居,标记其中已经使用的花种;
- 从
1到4选择第一个未被标记的花种; - 按编号顺序输出完整结果。
邻接表不需要排序:算法只关心邻居已经使用了哪些花种,不关心读取邻居的先后顺序。
正常、边界与错误情况
| 情况 | 预期行为 |
|---|---|
| 三角形 | 三个花园依次选择 1、2、3 |
完全图 K4 | 四个花园依次选择 1、2、3、4 |
| 路径或偶数环 | 仍按顶点编号贪心;若编号顺序不沿路径或环连续,也可能使用第三种花 |
| 多个连通分量 | 仍按全局花园编号依次处理,不需要单独遍历分量 |
| 孤立花园 | 没有已用颜色,选择花种 1 |
| 单花园无路径 | 输出 1 |
| 边的输入顺序混乱 | 不影响输出,结果只由图结构和花园编号决定 |
自环、重复路径、度数超过 3 或越界顶点 | 自动评分输入不会出现;无需额外校验,也不要输出错误提示 |
运行与评分
在本 Lab 目录执行:
make doctor
make run
make run CASE=001-sample
make score未安装 Make 时,在仓库根目录执行:
pnpm lab:doctor -- labs/chapter-06/exercise/E-06-03-flower-planting
pnpm lab:run -- labs/chapter-06/exercise/E-06-03-flower-planting
pnpm lab:score -- labs/chapter-06/exercise/E-06-03-flower-planting完成清单
复杂度分析
构建邻接表需要 O(n+m) 时间和空间。选花时,每个花园处理一次,每条无向路径会从两个端点的邻接表中各检查一次,因此选花需要 O(n+m) 时间。颜色数组和临时的四种花标记占用 O(n) 与 O(1) 空间,总时间复杂度和总空间复杂度均为 O(n+m)。
思考与复盘
- 为什么本题只需要检查已经选花的邻居,而不需要提前处理尚未选花的邻居?
- “最大度数不超过 3”如何保证四种花一定够用?如果只提供三种花,结论还成立吗?
- 为什么不排序邻接表也能得到唯一结果?哪些图算法会因为邻接表顺序不同而产生不同输出?
- LeetCode 原题允许返回任意合法方案,本 Lab 为什么要增加“选择最小可用花种”的规则?