无向图的连通分量计算
# 从某个顶点出发,访问到其能访问的所有其他顶点,这些顶点是属于一个连通分量的。
# 以此类推,将图的每个顶点都作为出发点一次。
1 local ConnectedComponent = {} 2 ConnectedComponent.__index = ConnectedComponent 3 4 function ConnectedComponent.new() 5 local obj = {} 6 setmetatable(obj, ConnectedComponent) 7 obj:ctor() 8 return obj 9 end 10 11 function ConnectedComponent:ctor() 12 self.graph = nil 13 self.vertexComponent = nil ---顶点所属的连通分量 14 self.componentId = 0 15 end 16 17 function ConnectedComponent:Calc(graph) 18 self.graph = graph 19 self.vertexComponent = {} 20 self.componentId = 0 21 local visited = {} 22 23 local function dfsVisitAllReachable(v) 24 visited[v] = true 25 self.vertexComponent[v] = self.componentId 26 27 local adjList = graph:GetAdjacent(v) 28 for i=1,#adjList do 29 local adjV = adjList[i] 30 if not visited[adjV] then 31 dfsVisitAllReachable(adjV) 32 end 33 end 34 end 35 36 for i=1,graph:GetVertexCount() do 37 local v = graph:GetVertex(i) 38 if not visited[v] then 39 dfsVisitAllReachable(v) --这个顶点能访问到的所有顶点属于同一个连通分量 40 self.componentId = self.componentId + 1 41 end 42 end 43 end 44 45 function ConnectedComponent:IsConnected(v1, v2) 46 return self.vertexComponent[v1] == self.vertexComponent[v2] --是否属于同一个连通分量 47 end 48 49 ---连通分量数量 50 function ConnectedComponent:GetCount() 51 return self.componentId 52 end 53 54 ---顶点所属连通分量id 55 function ConnectedComponent:GetComponentId(v) 56 return self.vertexComponent[v] 57 end 58 59 function ConnectedComponent:Dump() 60 local ccVertexListTb = {} ---连通分量的顶点队列 61 62 for i=1,self.graph:GetVertexCount() do 63 local v = self.graph:GetVertex(i) 64 local cid = self:GetComponentId(v) 65 local queue = ccVertexListTb[cid] 66 if nil == queue then 67 queue = {} 68 ccVertexListTb[cid] = queue 69 end 70 table.insert(queue, v) 71 end 72 73 for k_v, v_list in pairs(ccVertexListTb) do 74 print(table.concat(v_list, ",")) 75 end 76 end
使用下面的图进行测试:
1 function CreateGraph() 2 local g = Graph.new() 3 4 g:AddVertex("0") 5 g:AddVertex("1") 6 g:AddVertex("2") 7 g:AddEdge("0", "1") 8 g:AddEdge("0", "2") 9 10 g:AddVertex("3") 11 12 g:AddVertex("4") 13 g:AddVertex("5") 14 g:AddVertex("6") 15 g:AddVertex("7") 16 g:AddEdge("4", "5") 17 g:AddEdge("4", "6") 18 g:AddEdge("5", "7") 19 20 g:AddVertex("8") 21 g:AddVertex("9") 22 g:AddEdge("8", "9") 23 24 tostring(g) 25 return g 26 end 27 28 function Test1() 29 local g = CreateGraph() 30 local cc = ConnectedComponent.new() 31 cc:Calc(g) 32 cc:Dump() 33 end 34 Test1()
【参考】
图论算法——无向图的连通分量_日积月累,天道酬勤-CSDN博客_无向图的连通分量