保持没有周期或钻石的图形

时间:2012-05-20 05:03:23

标签: algorithm graph graph-algorithm

我想在hibernate / sql中维护一个有向图(即:一个简单的多对多自我关联),它没有循环或钻石。

“没有钻石”,我的意思是从任何节点到任何其他节点只有一条“路径”。我相信这两个规则意味着每个节点都可以被视为两棵树的根 - 一种是单向的,另一种是另一种。

这有一个众所周知的算法吗?问题归结为:“鉴于图形目前是格式良好的,如果我在A和B之间放置一个弧线,这会产生一个环还是一个钻石”?

1 个答案:

答案 0 :(得分:0)

如果您只是添加边缘而不是删除它们,请认为您可以通过使图表也具有disjoint set semantics来解决此问题。创建新边时,首先要检查两个节点是否已经是同一组的一部分。如果不是,则创建链接并在集合上执行联合。

这是一些Python代码,我希望即使你不了解Python,它也足以让伪代码易于理解。

class Node:
    # constructor
    def __init__(self):
        self.setParent = None
        self.graphParents = []
        self.graphChildren = []

    # disjoint set operations
    def getSetRoot(self):
        if self.setParent == None:
            return self
        else:
            self.setParent = self.setParent.getSetRoot()
            return self.setParent

    def joinSet(self, other):
        other.getSetRoot().setParent = self.getSetRoot()

    # graph operation
    def addChild(self, child):
        if self.getSetRoot() == child.getSetRoot():
            raise ValueError("Cannot add child!")
        else:
            self.graphChildren.append(child)
            child.graphParents.append(self)
            self.joinSet(child)

正如我所提到的,这只有在您从未移除任何边缘时才有效。这样做将需要为新分离的图形段重建不相交的集合,这可能非常慢。如果你很少删除边缘(比你添加的频率低很多倍),走这条路线可能仍然是合理的。