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);
}
}
}