以下是我对该问题的尝试。我没有能够想出更好的时间复杂度,但优化了暴力算法。
我逐个处理节点,只允许着色,使得相邻节点不具有相同的颜色。
我为每个中间(非完整)着色添加了一个上限估计。为此,我假设每个未着色的节点将以最高得分的颜色进行着色(仅允许使用与已着色邻居不同的颜色)。因此,在上限计算中,两个尚未着色的相邻节点都可以被着色为“红色”。利用这个估计,我构建了一个分支界定算法,当上限估计仍低于当前最大值时,终止当前搜索路径。
小图的运行时间小于1毫秒,中等图为15毫秒,大图为3.2秒。三个图的结果分别为46、77和194。
import time
import copy
def upperBoundScore(graph, dfsGraphOder, dfsIndex, coloring, scoring, currentScore):
maxAdditionalScore = 0;
for i in range(dfsIndex, len(dfsGraphOder)):
neighbourColors = {coloring[node] for node in graph[dfsGraphOder[i]]}
possibleColors = {1, 2, 3, 4} - neighbourColors
if len(possibleColors) < 1:
return -1
maxAdditionalScore += scoring[list(possibleColors)[0]]
return currentScore+maxAdditionalScore
def colorRemainingGraph(graph, dfsGraphOder, dfsIndex, coloring, scoring, currentScore):
global maxScore
global bestColoring
if dfsIndex == len(dfsGraphOder):
if currentScore > maxScore:
maxScore = currentScore
bestColoring = copy.deepcopy(coloring)
elif upperBoundScore(graph, dfsGraphOder, dfsIndex, coloring, scoring, currentScore) > maxScore:
neighbourColors ={coloring[node] for node in graph[dfsGraphOder[dfsIndex]]}
possibleColors = list({1, 2, 3, 4} - neighbourColors)
for c in possibleColors:
coloring[dfsGraphOder[dfsIndex]] = c
currentScore += scoring[c]
colorRemainingGraph(graph, dfsGraphOder, dfsIndex+1, coloring, scoring, currentScore)
currentScore -= scoring[c]
coloring[dfsGraphOder[dfsIndex]] = 0
graph = {2: [5, 6, 9], 5: [2, 4], 4: [5, 23], 6: [2, 7, 10], 3: [8, 16], 8: [3, 7, 12], 7: [6, 8, 10, 11], 9: [2, 10], 10: [6, 9, 7, 13, 14, 15, 17, 18], 11: [7, 12, 13], 12: [8, 11, 15, 16, 19], 13: [10, 11, 15], 14: [10, 15], 15: [10, 13, 12, 14, 17, 19], 16: [3, 12, 25, 27], 17: [10, 15, 18], 18: [10, 17, 19, 20], 19: [15, 18, 12, 27], 20: [18, 22, 24, 26, 27, 25], 22: [20], 23: [4, 24, 26], 24: [23, 20], 25: [16, 20], 26: [23, 20], 27: [19, 20, 16]}
scoring = {1:10, 2:6, 3:3, 4:1}
coloring = {node: 0 for node in graph.keys()}
nodeOrder = list(graph.keys())
maxScore = 0
bestColoring = {}
start = time.time()
colorRemainingGraph(graph, nodeOrder, 0, coloring, scoring, 0)
end = time.time()
print("Runtime: "+ str(end - start))
print("Max Score: "+str(maxScore))
print(bestColoring)
对于大图,得到的着色结果为(1=红色,2=绿色,3=蓝色,4=黄色):
{2: 1, 3: 1, 4: 1, 5: 2, 6: 2, 7: 1, 8: 2, 9: 2, 10: 3, 11: 2, 12: 1, 13: 1, 14: 1, 15: 4, 16: 2, 17: 2, 18: 1, 19: 2, 20: 2, 22: 1, 23: 2, 24: 1, 25: 1, 26: 1, 27: 1}
要验证算法输出的着色是否正确,可以使用以下代码,检查任何两个相邻节点是否具有相同的颜色。
def checkSolution(graph, coloring):
validColoring=1
for node in graph:
for neighbour in graph[node]:
if coloring[node] == coloring[neighbour]:
print("wrong coloring found "+ str(node) + " and " + str(neighbour) + " have the same color")
validColoring = 0
if validColoring:
print("Coloring is valid")