一、前言 
  关于本文中用到的这种图着色解决方法,不知道有没前人提出过。如果说没人提出过,那么就算是一个新的解决方法吧,具体性能对比没深入研究,但是求出的解基本是和Graph Coloring Instances网站里面的最优解一样的。  
  我们都知道,很多问题都可以转化成图着色问题来进行解决,所以本文的例子直接是无向图。  
  二、解决思路   
  不太成熟的想法:  
  要使得相邻点的颜色不同,着色方案有很多种,那么究竟哪种着色方案使用的颜色最少呢?  
  首先最开始看到这个问题时,我最开始的思路是每次用尽量少的颜色给尽量多的点上色。
   
     
 -> -> -> -> ->   
  以上是个简单的图,我选用的步骤为:  
  1、找出度最大的顶点2、3、5(度均为4)。  
  2、对2着色C1,然后遍历相邻点  
  3、给1着色C2  
  4、给3着色C2,和1冲突,着色C3  
  5、给5着色C2,不冲突  
  6、给4着色C2,与5冲突,着色C3  
  7、给4着色C1,不冲突  
  从一次性上完一种颜色入手:  
  本来是想实现上一个想法的,但是在梳理的过程中,有一个新的想法,即是通过与以前运筹学课程上学过的方法结合,较为高效且高质量地解决问题。  
  步骤如下:  
  步骤一、给未上色点集中度最大的顶点上色Ci,生成可同色点集,为与该顶点不相邻且未上色的点的集合  
  步骤二、遍历可同色点集,给点集中的点上色Ci,每上完一个点就生成一次可同色点集,为与上Ci点不相邻且未上色的点的集合,直到可同色点集为空  
  步骤三、更新未上色点集,i=i+1,回到步骤一  
  例:以下是myciel3.col数据的图,求最少能上几种颜色。  
     
  邻接矩阵为  
     
   每个顶点的度为4、4、4、4、4、3、3、3、3、3、5,度最大的顶点为第11个顶点。  
  1、给V11上色C1,可同色集为{V1,V2,V3,V4,V5}  
  2、给V1上色C1,可同色集为{V3,V5}  
   3、给V3上色C1,可同色集为{}  
  4、给V2上色C2,可同色集为{V4,V7,V9,V10}    
   5、给V4上色C2,可同色集为{V7,V9}  
  6、给V7上色C2,可同色集为{V9}  
  7、给V9上色C2,可同色集为{}  
   8、给V5上色C3,可同色集为{V6,V8,V10}  
  9、给V6上色C3,可同色集为{V10}  
  10、给V10上色C3,可同色集为{}  
  11、给V8上色C4,可同色集为{}  
  上色后的图:  
     
  颜色使用了4种,和已知最优解一样。  
   
  三、python代码实现 
    
 
  1 def getAdjMatrix(path):
 2     edge = []
 3     pointNum = 0
 4     with open(path, 'r') as fp:
 5         for line in fp.readlines():
 6             if line.startswith('p'):
 7                 pointNum = int(line.split()[2])
 8                 for i in range(pointNum):
 9                     edge.append([0 for i in range(pointNum)])
10             if line.startswith('e') and pointNum > 0:
11                 edge[int(line.split()[1]) - 1][int(line.split()[2]) - 1] = 1
12                 edge[int(line.split()[2]) - 1][int(line.split()[1]) - 1] = 1
13     return edge, pointNum
14 
15 
16 def main():
17     edge, pointNum = getAdjMatrix(r'F:\timFilm\test.txt')
18     print('')
19     for i in edge:
20         print('    ', end='')
21         for j in i:
22             print(j, end='\t\t')
23         print('\n')
24     colorNum = 0
25     disabled = []
26 
27     # 初始化color列表,用以记录每个顶点的着色情况
28     color = []
29     for i in range(pointNum):
30         color.append(0)
31     edgeNum = [sum(e) for e in edge]
32     for k in range(pointNum):
33         # 获取顶点最大度的索引值
34         maxEdgePoint = [i for i in range(pointNum) if edgeNum == max(edgeNum) and edgeNum != 0]
35         # 遍历最大度
36         for p in maxEdgePoint:
37             if p not in disabled:
38                 # 选取还未着色且度最大的点p开始着色
39                 color[p] = colorNum + 1
40                 disabled.append(p)
41                 edgeNum[p] = 0
42                 # temp用于查找该颜色可用来着色的下一个顶点
43                 temp = edge[p]
44                 for i in range(pointNum):
45                     if i not in disabled:
46                         if temp == 0:
47                             # 为不冲突的顶点着色
48                             color = colorNum + 1
49                             disabled.append(i)
50                             edgeNum = 0
51                             # 增加当前颜色的禁忌点
52                             temp = [x + y for (x, y) in zip(edge, temp)]
53                 # 需要新颜色
54                 colorNum = colorNum + 1
55 
56         # 每个顶点都已经着色
57         if 0 not in color:
58             break
59     print(color)
60     print(colorNum)
61 
62 
63 main() 
  
   
   
     |