我正在处理一个图形,其中有一定数量的节点,并且它们之间存在预定义的连接,而这些连接还没有“方向”。
问题是给所有边一个方向(例如,如果A和B之间存在连接,则给该边指定A-> B方向,或者B-> A),这样就不会有节点在接收端不止一个边缘。
示例: 对于此模型(A-B-C),A-> B-> C起作用,但A-> B <-C不起作用,因为B位于多个连接的接收端。尽管A <-B-> C可以工作,但因为B在两个连接的给定端。
我已经尝试过环路检测,但是这些节点可以任意连接,事实是,可能有很多环路可以彼此直接连接,也可以不直接连接,我找不到可以使用的解决方案信息。
在我的情况下,节点数可以是数千个,连接数可以是数百个。这也排除了蛮力。
并不能保证会有一个确定的解决方案,该算法的目的是找到一种连接数量最少的组合,从而使节点指向它们的边多于一个。
答案 0 :(得分:2)
这不是一个完整的算法,但是鉴于您在注释中对问题的描述,我认为这些步骤可能会将问题带回蛮力范围。
首先,您应该“修剪”图形。任何一级的节点都应修剪,其连接边指向修剪的节点。由于没有其他边缘可以指向该节点,因此我们知道此选择是最佳的。漂洗并重复直到所有剩余的节点都具有两个或更多的边缘。
接下来,如前所述,您应该排除任何孤立的节点。您实际上可以将其扩展到size <= 3
的已连接组件。这是因为对于最多三个节点,边的数量不能超过节点的数量,因此您可以随机分配一个边,其余的将就位。
现在,剩下的就是一堆大型的,高度连接的,相互连接的组件。您实际上可以再进行一次检查,看看是否有任何一个形成单个循环(所有节点的度数为2),然后随机分配一个边,但这可能是一种相当罕见的情况。您可能只想开始独立地强行强制其中的每一个。最好首先从边缘数量最少的节点开始,在分配边缘时更新节点的程度(并像以前一样修剪一个边缘的任何程度),并根据需要进行回溯。
答案 1 :(得分:2)
这是answer by Dillon Davis的延续。
在移除树状分支并解决了简单的循环之后,其余图的度数为2或更大。我建议(出于分析图形的目的)可以删除2度的所有节点。
请允许我通过示例进行解释。在此示例中,当节点用数字表示时,该数字是节点的度数。当一个节点用字母表示时,该节点的阶数为2。因此图
3 - A - B - C - 4
表示3级节点,该节点连接到2级节点链,连接到4级节点。
该图的这一部分的两个理想选择是
3 -> A -> B -> C -> 4
3 <- A <- B <- C <- 4
从每个字母节点恰好有一个输入边的意义上说,这是理想的。我建议这些不仅仅是理想的选择,它们是仅 的选择。考虑第一个理想的解决方案
3 -> A -> B -> C -> 4
如果节点4的传入边缘过多,我们可以通过将边缘反转为C来减少其计数,从而得到
3 -> A -> B -> C <- 4
但是这并没有改善情况,它将“太多的边变成4” 与“太多的边变成C” 。随后反转C和B之间的边会解决C,但会破坏B。继续沿链条反转,最终A和3之间的连接会反转,我们得出了第二个理想解决方案。
这促使我得出结论(出于分析目的)
3 - A - B - C - 4
等效于
3 - 4
那么这在简化问题上有什么用。考虑下图:
除去节点A和B时,其余边缘将顶部节点3连接到其自身,因此可以除去边缘。对于C和D同样如此。它使图形具有单个边。选择该边缘的任一方向。然后,通过为简单周期A-B-3选择一个方向,并为简单周期C-D-3独立选择一个方向来完成解决方案。
这是另一个例子:
在这种情况下,删除A和B将在其余节点之间创建冗余边。删除冗余边缘后,为边缘选择任一方向。边缘的方向决定了循环3-A-3和循环3-B-3的方向。
答案 2 :(得分:1)
我不确定是否要添加其他答案,但是答案by user3386109让我深入了解了我认为是完整的解决方案,而且我认为它与我最初的回答的精神有很大不同,无法包含作为修改。
回顾一下,我们提供了一些工具:
我们可以最佳地修剪单个边缘的节点,重复此过程直至完成
我们可以在一个简单的周期(连接的组件中只有2级节点)上为任意边指定方向,其余的(最佳)跟随。
在更复杂的循环中具有两个边缘的节点可以暂时忽略,因为它们的边缘方向将由度数较高的节点分配。
在阅读了最后一点之后,问题本身变得更加清晰了。修剪完项目符号1中的一级节点后,所有其余节点至少具有两个边缘。我们可以肯定地说,在最佳图中,这些节点中的每个节点将至少具有一个指向它们的方向性边。作为证明,由于每个节点至少具有两个边,但是连接的组件并不是一个简单的循环(否则将在项目符号2中消除),因此我们的边比节点多。如果任何节点的零边缘指向其,可以将这些边缘之一反转以减少冲突边缘的数量,或“释放”另一个节点以使其零边缘向内,然后执行相同的操作。
有了这些知识,我们知道冲突的最小数量(指向已经有边指向其的节点的额外边)等于边的数量减去修剪后的图中顶点的数量。我们还可以得出结论,只要我们设法将至少一条边指向每个节点,无论我们如何分散冲突边,我们都将获得一个最优图。
最初,我试图基于第三个项目来起草算法以完成此任务,但事实证明,答案实际上甚至比这简单得多。我们无意中创建一个没有任何指向其边缘的节点的唯一方法是主动将所有边缘指向远离该节点的方向。解决方案是在连接的组件中选取单个边,并随机为其分配方向。然后,从其指向的节点向外进行搜索(DFS,BFS等),并在沿行进的方向上为边沿分配方向。您到达的任何节点都将指向其边缘(到达该边缘所用的边缘),并且根节点具有您手动为其分配的边缘。
最后,这将生成一个图形,该图形具有指向节点的 extra 个边的最少数量。相反,如果希望最大程度地减少包含冲突边的节点的数量,请解决上述问题,然后形成度数为3或更高的节点及其连接边的子图。解决此子图的最小顶点覆盖,然后反转连接不在最小顶点覆盖中但包含冲突边的节点的边与最小顶点覆盖中对应节点的边的方向。