解決圖着色問題 python代碼實現


  一、前言

  關於本文中用到的這種圖着色解決方法,不知道有沒前人提出過。如果說沒人提出過,那么就算是一個新的解決方法吧,具體性能對比沒深入研究,但是求出的解基本是和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[i] == max(edgeNum) and edgeNum[i] != 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[i] == 0:
47                             # 為不沖突的頂點着色
48                             color[i] = colorNum + 1
49                             disabled.append(i)
50                             edgeNum[i] = 0
51                             # 增加當前顏色的禁忌點
52                             temp = [x + y for (x, y) in zip(edge[i], 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()

 

 

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM