5-28。图G的关节顶点是其删除断开G的顶点。设G是具有n个顶点和m个边的图。给出一个简单的O(n + m)算法,用于找到不是关节顶点的G的顶点,即。 ,其删除不会断开G.
5-29。继续上一个问题,给出一个O(n + m)算法,该算法找到n个顶点的删除顺序,这样就不会删除图形。 (提示:想想DFS / BFS。)
5-28,这是我的想法:
我会做一个dfs但不完整。 完成处理的第一个顶点将是一个非关节顶点,因为它必须是一个叶子,或一个背面指向其祖先的叶子(它也不是关节顶点)
适用于5-29
我还不确定如何做得很好。我想到的是,在图表中,周期中的任何顶点都不能安全删除。此外,如果没有循环,那么从dfs树向后删除顶点也是安全的。
有人可以给我一些提示或告诉我,我的想法是正确还是错误?
答案 0 :(得分:1)
我认为你对5-28的解决方案是正确的,它保证找到一个在O(n + m)时间内没有发音的节点。
对于5-29,我认为一种方法是基于你对5-28的解决方案。在执行dfs时,请确保每个节点何时离开堆栈(完成处理的时间)。正如你所说,首先离开的一个必须是一个叶子节点,所以删除它不会断开图形。然后你可以删除节点第二个离开堆栈,当我们删除第一个节点时它也必须是一个叶子节点。 因此我们可以按照与DFS一样从堆栈弹出时相反的顺序删除节点。这样做只需要一次DFS传递,因此运行时间为O(n + m)。
另一种简单的方法是使用BFS。对于5.28,删除任何具有最大深度的节点都不会使图形断开连接。因为深度较小的节点可以到达每个其他节点。因此对于5.29,我们可以按降序排序所有节点的排序深度。而且,我们只需要1个BFS,因此运行时间为O(n + m)。我认为人们更容易理解这种方法。
答案 1 :(得分:0)
5-29: 从5-28扩展你的想法,当你完成顶点处理时,它是一个非关节顶点,所以删除它。然后继续DFS,每次处理完另一个顶点后,也将其删除。由于您删除了完成处理的先前顶点,因此每次完成顶点处理时,实际上是第一次完成顶点处理(对于没有先前删除顶点的图形)。
另一种方法,更容易证明,效率稍低(但仍然是O(V + E)) - 从图中克服一个DFS树,然后进行拓扑排序,然后从最后一个逐个删除顶点排序图中的一个并移回第一个。在每一步中,您删除最后一个,并且您确定(因为它是拓扑排序图)它不会指向任何其他节点,这意味着除了通向它的边之外不会删除任何边。这意味着所有其他节点仍然可以从第一个节点到达,如果图形是双向的,那么所有节点也可以到达第一个节点,使其连接。
答案 2 :(得分:-1)
对于第一个问题,我将从图中删除要测试的顶点,然后从任何其他顶点开始运行DFS / BFS,计算访问顶点的数量。如果它小于(original size - 1)
,则测试的顶点是清晰度顶点。
同样的想法适用于第二个问题。您随机选择一个顶点并将其删除,这通常会将图形切割成两个块。如果删除的顶点不是铰接顶点,则两个块中的一个必须为空。否则,两个块都有一些顶点,在这种情况下,BOTH块中的所有顶点都必须在最后一个"安全删除"中排在这个顶点的前面。顺序,虽然决定首先完全删除哪个块并不重要。所以我们可以编写一个像这样的递归函数:
vertex[] safe_order_cut (vertex[] v)
if (v.length==0) return empty_vertex_list;
vertex x = randomly_pick(v);
vertex v1[], v2[];
cut_graph(v,x,v1,v2);
return safe_order_cut(v1) + safe_order_cut(v2) + x;
在图论中已经广泛研究了连通性问题(以及相关的切割顶点问题)。如果您有兴趣,可以阅读维基页面以获取更多算法。