P86 - 图着色

2026-09-07 00:00    #Haskell   #99题   #图  

P86 - 图着色

Color a graph with the Welsh-Powell algorithm

官方模块:Problems.P86 核心函数:colorGraph


← P85 图同构 | P87 深度优先遍历 →


算法

Welsh-Powell 是贪心着色:按度数从高到低处理顶点,每个顶点选择尚未被邻居使用的最小正整数颜色。它保证合法,但不保证颜色数全局最少。

实现

方法一:Welsh-Powell 贪心

 1import Data.List (sortOn)
 2import Data.Ord (Down(..))
 3
 4colorGraph :: G -> [(Vertex, Int)]
 5colorGraph graph = Map.toAscList (foldl color Map.empty order)
 6  where
 7    vs = Set.toList (fst (canonical graph))
 8    order = sortOn (Down . Set.size . (`neighbors` graph)) vs
 9
10    color assigned vertex = Map.insert vertex available assigned
11      where
12        used = Set.fromList
13          [c | neighbor <- Set.toList (neighbors vertex graph)
14             , Just c <- [Map.lookup neighbor assigned]]
15        available = head [c | c <- [1..], Set.notMember c used]

方法二:回溯求最少颜色

 1colorGraphOptimal :: G -> [(Vertex, Int)]
 2colorGraphOptimal graph = Map.toAscList $ head
 3  [coloring
 4  | colorCount <- [0..length vertices]
 5  , Just coloring <- [assign colorCount vertices Map.empty]
 6  ]
 7  where
 8    vertices = sortOn
 9      (Down . Set.size . (`neighbors` graph))
10      (Set.toList (fst (canonical graph)))
11
12    assign _ [] coloring = Just coloring
13    assign colorCount (vertex:rest) coloring = firstJust
14      [assign colorCount rest (Map.insert vertex color coloring)
15      | color <- [1..colorCount]
16      , all (\neighbor -> Map.lookup neighbor coloring /= Just color)
17            (Set.toList (neighbors vertex graph))]
18
19    firstJust [] = Nothing
20    firstJust (Just value:_) = Just value
21    firstJust (Nothing:rest) = firstJust rest

从 0、1、2……种颜色依次尝试,找到的第一个完整着色必然使用最少颜色。高度数顶点优先可以提前制造冲突,但最坏情况仍是指数搜索。

方法对比

方法保证代价
Welsh-Powell快速得到合法着色不保证颜色数最少
回溯得到最少颜色着色指数级,只适合小图

测试

1>>> colorGraph (toG (Paths [[1,2,3,1]]))
2[(1,1),(2,2),(3,3)]
3>>> let graph = toG (Paths [[1,2,3,4],[1,4]])
4>>> let coloring = Map.fromList (colorGraph graph)
5>>> all (\(u,v) -> coloring Map.! u /= coloring Map.! v)
6...     (Set.toList (snd (canonical graph)))
7True
8>>> maximum (map snd (colorGraphOptimal (toG (Paths [[1,2,3,1]]))))
93

在简单列表和集合实现下,复杂度约 O(n2)O(n^2)

参考


← P85 图同构 | P87 深度优先遍历 →