Java 用参与的循环数标记边

Java 用参与的循环数标记边,java,graph,digraphs,Java,Graph,Digraphs,给定一个图G=(V,E),使用DFS,如何用它参与的简单循环数标记每条边?当我从图中提取强连接的组件时,我已经用post顺序标记了节点,所以也许我可以以某种方式使用这些信息 private Integer labelEdges(Node currentNode, Set<Node> component) { Integer numLoops = 0; currentNode.onStack = true; for (Edge outEdge : curre

给定一个图
G=(V,E)
,使用DFS,如何用它参与的简单循环数标记每条边?当我从图中提取强连接的组件时,我已经用post顺序标记了节点,所以也许我可以以某种方式使用这些信息

private Integer labelEdges(Node currentNode, Set<Node> component) {

    Integer numLoops = 0;
    currentNode.onStack = true;

    for (Edge outEdge : currentNode.getEdges()) {
        Node nextNode = outEdge.getEnd();
        if (component.contains(nextNode)) {
            if (nextNode.onStack) {
                // loop
                numLoops += 1;
            }
            else {
                numLoops += labelEdges(nextNode, component);
            }
            outEdge.cycles = numLoops;
        }

    }
    currentNode.onStack = false;

    return numLoops;
}
专用整数标签(节点currentNode,设置组件){
整数numLoops=0;
currentNode.onStack=true;
对于(Edge outEdge:currentNode.GetEdge()){
节点nextNode=outEdge.getEnd();
if(组件包含(下一个节点)){
if(nextNode.onStack){
//环路
numLoops+=1;
}
否则{
numLoops+=标签(下一个节点,组件);
}
outEdge.cycles=numLoops;
}
}
currentNode.onStack=false;
返回numLoops;
}

我似乎无法清楚地解释这件事。有人能给我指出正确的方向吗?

如果不看完整的代码,很难给出完整的答案,但我认为这会有所帮助。请注意,提供的链接用于无向图

我认为你应该把这个问题分成两部分:

1.查找图形中的所有循环(将它们保存在哈希表或类似文件中)

2.查找这些周期中的哪些包含特定节点

1的解决方案:对于第一步,有许多在线算法,例如,只需稍加调整即可工作,或者计算循环数,您可以更改它以保存找到的循环

2的解决方案:这取决于如何保存循环,但这是一个简单的搜索算法


请注意,如果您只想一次找到一个节点的答案,则此解决方案不是最佳解决方案,但如果您希望能够找到任何给定节点和任何给定时间的循环数,则此解决方案确实很好。

我最后添加了一个额外的
映射
以前的边
,跟踪要在回溯中回溯的边。然后,
unwindStack
函数遍历此链表,递增
边。循环
,直到到达结束循环的
节点(
loopNode
):

private void labelEdges(节点currentNode,设置组件){
onStack.put(currentNode,Boolean.TRUE);
对于(Edge outEdge:currentNode.GetEdge()){
节点nextNode=outEdge.getEnd();
if(组件包含(下一个节点)){
//将边放在PreviousEdge堆栈上
如果(!previousEdges.containsKey(nextNode)){
previousEdges.put(nextNode,new Stack());
}
previousEdges.get(nextNode.push(outEdge);
if(onStack.getOrDefault(nextNode,false)){
//发现循环
展开堆栈(nextNode,nextNode);
//将上一条边从堆栈中弹出,以便我们撤消任何
//覆盖另一个分支的历史记录。
previousEdges.get(nextNode.pop();
}
否则{
//递归调用此函数
标签(下一个节点,组件);
}
}
}
onStack.put(currentNode,Boolean.FALSE);
}
私有无效展开堆栈(节点currentNode、节点loopNode){
前边缘;
试一试{
previousEdge=previousEdge.get(currentNode.peek();
}捕获(清空堆栈异常){
previousEdge=null;
}
如果(previousEdge!=null){
//将edgeCycles条目增加1
merge(previousEdge,1,Integer::sum);
节点previousNode=previousEdge.getStart();
if(previousNode!=loopNode){
展开堆栈(previousNode、loopNode);
}
}
}
…如果您是
Edge
的“所有者”,那么您可以(简单地)在其上引入一个实例变量。(例如,
numOfCircles
)。。。并在DFS中增加它…如您认为合适。(如果没有…您可以创建并维护
地图
private void labelEdges(Node currentNode, Set<Node> component) {

    onStack.put(currentNode, Boolean.TRUE);

    for (Edge outEdge : currentNode.getEdges()) {
        Node nextNode = outEdge.getEnd();
        if (component.contains(nextNode)) {

            // put the edge on the previousEdges stack
            if (!previousEdges.containsKey(nextNode)) {
                previousEdges.put(nextNode, new Stack<>());
            }
            previousEdges.get(nextNode).push(outEdge);

            if (onStack.getOrDefault(nextNode, false)) {
                // found loop
                unwindStack(nextNode, nextNode);
                // pop the previousEdge off the stack, so that we undo any
                // overwriting of history for another branch.
                previousEdges.get(nextNode).pop();

            }
            else {
                // recursively call this function
                labelEdges(nextNode, component);
            }
        }
    }
    onStack.put(currentNode, Boolean.FALSE);
}

private void unwindStack(Node currentNode, Node loopNode) {
    Edge previousEdge;
    try {
        previousEdge = previousEdges.get(currentNode).peek();
    } catch (EmptyStackException e) {
        previousEdge = null;
    }
    if (previousEdge != null) {
        // increment edgeCycles entry by 1
        edgeCycles.merge(previousEdge, 1, Integer::sum);
        Node previousNode = previousEdge.getStart();
        if (previousNode != loopNode) {
            unwindStack(previousNode, loopNode);
        }
    }
}