题目
有一个无向红黑图,我们对这张图的每个节点进行染色,只能染成黑色或者红色,要求相邻节点不能同为红色,求有几种染法?
思路
回溯
代码解析
color_list用来保存每个节点染的颜色,0表示没有染色,1表示黑色,2表示红色
neighbor_list保存每个节点的所有相邻节点
回溯核心代码:
input:节点索引,从0号节点开始染色
base_case:最后一个节点成功染色,返回一种方法
分别遍历两种颜料(1为黑色和2为红色),染过一次黑色后,使用black_color标记当前节点已经染过黑色,当前层不再染黑色;
Python代码
class Solution:
def can_dyeing(self, index, neighbor_list, color_list):
for neighbor in neighbor_list[index]:
if color_list[neighbor] == 2:
return False
return True
def to_color_map(self, number, edge, relationship):
ans = []
color_list = [0] * number # 每个点的染色情况,0表示没有染色,1表示染了黑色,2表示染了红色
neighbor_list = [[] for _ in range(number)] # 点的所有邻居
for a, b in relationship:
neighbor_list[a].append(b)
neighbor_list[b].append(a)
def backtrace(node_index):
nonlocal neighbor_list, color_list, number, ans
"""
node_index:当前待染色点的索引
:param node_index:
:return:
"""
if node_index == number:
ans.append(color_list[:])
return
black_color = 0 # 1表示当前层已经染过黑色,0表示还没有染过黑色
for c in range(1, 3): # 染色
if c == 2 and self.can_dyeing(node_index, neighbor_list, color_list):
# 当前节点可以染红色
color_list[node_index] = c
else:
if black_color:
# 剪枝,当前层已经染过黑色
continue
color_list[node_index] = 1
black_color = 1
backtrace(node_index+1)
color_list[node_index] = 0 # 回溯
backtrace(0)
print(ans)
return len(ans)
if __name__ == '__main__':
number = 4
edge = 3
relationship = [[0, 1], [0, 2], [1, 2], [3, 3]]
obj = Solution()
res = obj.to_color_map(number, edge, relationship)
print(res)