给地图中的相邻区域交替着色时,沿一条链交替很容易,但闭合连接可能让要求互相冲突。需要检查所有连接以及不相连的分量,而不是只从第一个节点走一小段。
以下是一组可按记录复查的虚构游戏例子。它先固定输入、单位和执行顺序,再展示每一步结果。读者可以用纸笔挑出几步核对,不需要依赖具体游戏的后台数据。
明确规则与输入
八个节点构成无向图,每条边要求两端颜色不同。按编号从小到大选择尚未着色的起点,起点涂零,按邻接编号顺序广度遍历,未着色邻居涂相反颜色。已经同色的相邻边记为冲突,仍继续记录全图。
八节点无向边[(0, 1), (0, 3), (1, 2), (1, 4), (1, 6), (2, 3), (4, 7), (5, 6), (6, 7)]
完整计算过程
处理节点0,颜色0,邻居[1, 3],新着色[编号,颜色][[1, 1], [3, 1]],待处理队列[1, 3]。已着色邻居保留原色,稍后统一核对边约束。
处理节点1,颜色1,邻居[0, 2, 4, 6],新着色[编号,颜色][[2, 0], [4, 0], [6, 0]],待处理队列[3, 2, 4, 6]。已着色邻居保留原色,稍后统一核对边约束。
处理节点3,颜色1,邻居[0, 2],新着色[编号,颜色][],待处理队列[2, 4, 6]。已着色邻居保留原色,稍后统一核对边约束。
处理节点2,颜色0,邻居[1, 3],新着色[编号,颜色][],待处理队列[4, 6]。已着色邻居保留原色,稍后统一核对边约束。
处理节点4,颜色0,邻居[1, 7],新着色[编号,颜色][[7, 1]],待处理队列[6, 7]。已着色邻居保留原色,稍后统一核对边约束。
处理节点6,颜色0,邻居[1, 5, 7],新着色[编号,颜色][[5, 1]],待处理队列[7, 5]。已着色邻居保留原色,稍后统一核对边约束。
处理节点7,颜色1,邻居[4, 6],新着色[编号,颜色][],待处理队列[5]。已着色邻居保留原色,稍后统一核对边约束。
处理节点5,颜色1,邻居[6],新着色[编号,颜色][],待处理队列[]。已着色邻居保留原色,稍后统一核对边约束。
最终颜色[0, 1, 0, 1, 0, 1, 0, 1],同色相邻冲突[];所有边均异色,可用两色满足约束。
独立核对与边界
独立枚举八个节点全部二进制配色,寻找是否存在满足所有边的方案。找到方案时应与遍历的无冲突结论一致;无方案说明连接约束本身不能仅用两色满足,并非换个起点就能解决。
颜色零和一只是两种标记,可以整片互换。无向图中的奇数长度环会造成交替颜色冲突,偶数环本身不一定有问题。本例不要求相邻以外的节点颜色不同,也不讨论最少需要第三种以上颜色的数量。
练习时只改变一个条件,先判断哪些中间步骤应当受影响,再重新计算。要把空状态、数值零和未能确定的结果分开。边界约定不同可能产生不同答案,复查的目标是确认输入、过程与规则一致,而不是只追求最后一个数字看起来相同。
