6 * $Date: 2012-07-15 15:35:29 +0200 (So, 15. Jul 2012) $
7 ***************************************************************/
10 * \brief Implementation of simple graph algorithms
12 * \author Carsten Gutwenger, Sebastian Leipert
15 * This file is part of the Open Graph Drawing Framework (OGDF).
19 * See README.txt in the root directory of the OGDF installation for details.
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * Version 2 or 3 as published by the Free Software Foundation;
25 * see the file LICENSE.txt included in the packaging of this file
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
35 * You should have received a copy of the GNU General Public
36 * License along with this program; if not, write to the Free
37 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
38 * Boston, MA 02110-1301, USA.
40 * \see http://www.gnu.org/copyleft/gpl.html
41 ***************************************************************/
44 #include <ogdf/basic/simple_graph_alg.h>
45 #include <ogdf/basic/SList.h>
46 #include <ogdf/basic/Stack.h>
47 #include <ogdf/basic/GraphCopy.h>
48 #include <ogdf/basic/tuples.h>
49 #include <ogdf/basic/BoundedStack.h>
55 //---------------------------------------------------------
56 // isLoopFree(), makeLoopFree()
57 // testing for self-loops, removing self-loops
58 //---------------------------------------------------------
59 bool isLoopFree(const Graph
&G
)
63 if(e
->isSelfLoop()) return false;
69 void makeLoopFree(Graph
&G
)
72 for (e
= G
.firstEdge(); e
; e
= eNext
) {
74 if (e
->isSelfLoop()) G
.delEdge(e
);
79 //---------------------------------------------------------
80 // isParallelFree(), makeParallelFree()
81 // testing for multi-edges, removing multi-edges
82 //---------------------------------------------------------
84 void parallelFreeSort(const Graph
&G
, SListPure
<edge
> &edges
)
88 BucketSourceIndex bucketSrc
;
89 edges
.bucketSort(0,G
.maxNodeIndex(),bucketSrc
);
91 BucketTargetIndex bucketTgt
;
92 edges
.bucketSort(0,G
.maxNodeIndex(),bucketTgt
);
96 bool isParallelFree(const Graph
&G
)
98 if (G
.numberOfEdges() <= 1) return true;
100 SListPure
<edge
> edges
;
101 parallelFreeSort(G
,edges
);
103 SListConstIterator
<edge
> it
= edges
.begin();
105 for(it
= ++it
; it
.valid(); ++it
, ePrev
= e
) {
107 if (ePrev
->source() == e
->source() && ePrev
->target() == e
->target())
115 int numParallelEdges(const Graph
&G
)
117 if (G
.numberOfEdges() <= 1) return 0;
119 SListPure
<edge
> edges
;
120 parallelFreeSort(G
,edges
);
123 SListConstIterator
<edge
> it
= edges
.begin();
125 for(it
= ++it
; it
.valid(); ++it
, ePrev
= e
) {
127 if (ePrev
->source() == e
->source() && ePrev
->target() == e
->target())
136 //---------------------------------------------------------
137 // isParallelFreeUndirected(), makeParallelFreeUndirected()
138 // testing for (undirected) multi-edges, removing (undirected) multi-edges
139 //---------------------------------------------------------
141 void parallelFreeSortUndirected(const Graph
&G
,
142 SListPure
<edge
> &edges
,
143 EdgeArray
<int> &minIndex
,
144 EdgeArray
<int> &maxIndex
)
150 int srcIndex
= e
->source()->index(), tgtIndex
= e
->target()->index();
151 if (srcIndex
<= tgtIndex
) {
152 minIndex
[e
] = srcIndex
; maxIndex
[e
] = tgtIndex
;
154 minIndex
[e
] = tgtIndex
; maxIndex
[e
] = srcIndex
;
158 BucketEdgeArray
bucketMin(minIndex
), bucketMax(maxIndex
);
159 edges
.bucketSort(0,G
.maxNodeIndex(),bucketMin
);
160 edges
.bucketSort(0,G
.maxNodeIndex(),bucketMax
);
164 bool isParallelFreeUndirected(const Graph
&G
)
166 if (G
.numberOfEdges() <= 1) return true;
168 SListPure
<edge
> edges
;
169 EdgeArray
<int> minIndex(G
), maxIndex(G
);
170 parallelFreeSortUndirected(G
,edges
,minIndex
,maxIndex
);
172 SListConstIterator
<edge
> it
= edges
.begin();
174 for(it
= ++it
; it
.valid(); ++it
, ePrev
= e
) {
176 if (minIndex
[ePrev
] == minIndex
[e
] && maxIndex
[ePrev
] == maxIndex
[e
])
184 int numParallelEdgesUndirected(const Graph
&G
)
186 if (G
.numberOfEdges() <= 1) return 0;
188 SListPure
<edge
> edges
;
189 EdgeArray
<int> minIndex(G
), maxIndex(G
);
190 parallelFreeSortUndirected(G
,edges
,minIndex
,maxIndex
);
193 SListConstIterator
<edge
> it
= edges
.begin();
195 for(it
= ++it
; it
.valid(); ++it
, ePrev
= e
) {
197 if (minIndex
[ePrev
] == minIndex
[e
] && maxIndex
[ePrev
] == maxIndex
[e
])
206 //---------------------------------------------------------
207 // isConnected(), makeConnected()
208 // testing connectivity, establishing connectivity
209 //---------------------------------------------------------
211 bool isConnected(const Graph
&G
)
213 node v
= G
.firstNode();
214 if (v
== 0) return true;
217 NodeArray
<bool> visited(G
,false);
218 BoundedStack
<node
> S(G
.numberOfNodes());
228 node w
= adj
->twinNode();
236 return (count
== G
.numberOfNodes());
240 void makeConnected(Graph
&G
, List
<edge
> &added
)
243 if (G
.numberOfNodes() == 0) return;
244 NodeArray
<bool> visited(G
,false);
245 BoundedStack
<node
> S(G
.numberOfNodes());
250 if (visited
[u
]) continue;
253 int minDeg
= u
->degree();
264 node w
= adj
->twinNode();
269 int wDeg
= w
->degree();
279 added
.pushBack(G
.newEdge(pred
,vMinDeg
));
285 int connectedComponents(const Graph
&G
, NodeArray
<int> &component
)
294 if (component
[v
] != -1) continue;
297 component
[v
] = nComponent
;
302 forall_adj_edges(e
,w
) {
303 node x
= e
->opposite(w
);
304 if (component
[x
] == -1) {
305 component
[x
] = nComponent
;
317 //return the isolated nodes too, is used in incremental layout
318 int connectedIsolatedComponents(const Graph
&G
, List
<node
> &isolated
,
319 NodeArray
<int> &component
)
328 if (component
[v
] != -1) continue;
331 component
[v
] = nComponent
;
335 if (w
->degree() == 0) isolated
.pushBack(w
);
337 forall_adj_edges(e
,w
) {
338 node x
= e
->opposite(w
);
339 if (component
[x
] == -1) {
340 component
[x
] = nComponent
;
353 //---------------------------------------------------------
354 // isBiconnected(), makeBiconnected()
355 // testing biconnectivity, establishing biconnectivity
356 //---------------------------------------------------------
357 static node
dfsIsBicon (const Graph
&G
, node v
, node father
,
358 NodeArray
<int> &number
, NodeArray
<int> &lowpt
, int &numCount
)
362 lowpt
[v
] = number
[v
] = ++numCount
;
365 forall_adj_edges(e
,v
) {
366 node w
= e
->opposite(v
);
367 if (v
== w
) continue; // ignore self-loops
369 if (number
[w
] == 0) {
370 if (first_son
== 0) first_son
= w
;
372 node cutVertex
= dfsIsBicon(G
,w
,v
,number
,lowpt
,numCount
);
373 if (cutVertex
) return cutVertex
;
376 if (lowpt
[w
] >= number
[v
] && (w
!= first_son
|| father
!= 0))
379 if (lowpt
[w
] < lowpt
[v
]) lowpt
[v
] = lowpt
[w
];
383 if (number
[w
] < lowpt
[v
]) lowpt
[v
] = number
[w
];
391 bool isBiconnected(const Graph
&G
, node
&cutVertex
)
393 if (G
.empty()) return true;
395 NodeArray
<int> number(G
,0);
396 NodeArray
<int> lowpt(G
);
399 cutVertex
= dfsIsBicon(G
,G
.firstNode(),0,number
,lowpt
,numCount
);
401 return (numCount
== G
.numberOfNodes() && cutVertex
== 0);
405 static void dfsMakeBicon (Graph
&G
,
407 NodeArray
<int> &number
,
408 NodeArray
<int> &lowpt
,
414 lowpt
[v
] = number
[v
] = ++numCount
;
417 forall_adj_edges(e
,v
) {
418 node w
= e
->opposite(v
);
419 if (v
== w
) continue; // ignore self-loops
421 if (number
[w
] == 0) {
423 dfsMakeBicon(G
,w
,v
,number
,lowpt
,numCount
,added
);
426 if (lowpt
[w
] >= number
[v
]) {
427 if (predSon
== 0 && father
!= 0)
428 added
.pushBack(G
.newEdge(w
,father
));
430 else if (predSon
!= 0)
431 added
.pushBack(G
.newEdge(w
,predSon
));
434 if (lowpt
[w
] < lowpt
[v
]) lowpt
[v
] = lowpt
[w
];
439 if (number
[w
] < lowpt
[v
]) lowpt
[v
] = number
[w
];
445 void makeBiconnected(Graph
&G
, List
<edge
> &added
)
447 if (G
.empty()) return;
449 makeConnected(G
,added
);
451 NodeArray
<int> number(G
,0);
452 NodeArray
<int> lowpt(G
);
455 dfsMakeBicon(G
,G
.firstNode(),0,number
,lowpt
,numCount
,added
);
459 //---------------------------------------------------------
460 // biconnectedComponents()
461 // computing biconnected components
462 //---------------------------------------------------------
463 static void dfsBiconComp (const Graph
&G
,
466 NodeArray
<int> &number
,
467 NodeArray
<int> &lowpt
,
468 StackPure
<node
> &called
,
469 EdgeArray
<int> &component
,
473 lowpt
[v
] = number
[v
] = ++nNumber
;
477 forall_adj_edges(e
,v
) {
478 node w
= e
->opposite(v
);
479 if (v
== w
) continue; // ignore self-loops
481 if (number
[w
] == 0) {
483 dfsBiconComp(G
,w
,v
,number
,lowpt
,called
,component
,
486 if (lowpt
[w
] < lowpt
[v
]) lowpt
[v
] = lowpt
[w
];
490 if (number
[w
] < lowpt
[v
]) lowpt
[v
] = number
[w
];
494 if (father
&& (lowpt
[v
] == number
[father
])) {
497 w
= called
.top(); called
.pop();
499 forall_adj_edges(e
,w
) {
500 if (number
[w
] > number
[e
->opposite(w
)])
501 component
[e
] = nComponent
;
510 int biconnectedComponents(const Graph
&G
, EdgeArray
<int> &component
)
512 if (G
.empty()) return 0;
514 StackPure
<node
> called
;
515 NodeArray
<int> number(G
,0);
516 NodeArray
<int> lowpt(G
);
517 int nNumber
= 0, nComponent
= 0, nIsolated
= 0;
521 if (number
[v
] == 0) {
522 bool isolated
= true;
524 forall_adj_edges(e
,v
)
525 if (!e
->isSelfLoop()) {
526 isolated
= false; break;
532 dfsBiconComp(G
,v
,0,number
,lowpt
,called
,component
,
537 return nComponent
+ nIsolated
;
541 //---------------------------------------------------------
543 // testing triconnectivity
544 //---------------------------------------------------------
545 bool isTriconnectedPrimitive(const Graph
&G
, node
&s1
, node
&s2
)
549 if (isConnected(G
) == false)
552 if (isBiconnected(G
,s1
) == false)
555 if (G
.numberOfNodes() <= 3)
559 GraphCopySimple
GC(G
);
561 // for each node v in G, we test if G \ v is biconnected
565 node vC
= GC
.copy(v
), wC
;
567 // store adjacent nodes
568 SListPure
<node
> adjacentNodes
;
570 forall_adj_edges(eC
,vC
) {
571 wC
= eC
->opposite(vC
);
572 // forget self-loops (vC would no longer be in GC!)
574 adjacentNodes
.pushBack(wC
);
579 // test for biconnectivity
580 if(isBiconnected(GC
,wC
) == false) {
581 s1
= v
; s2
= GC
.original(wC
);
585 // restore deleted node with adjacent edges
587 SListConstIterator
<node
> it
;
588 for(it
= adjacentNodes
.begin(); it
.valid(); ++it
)
596 //--------------------------------------------------------------------------
598 //--------------------------------------------------------------------------
599 void triangulate(Graph
&G
)
601 OGDF_ASSERT(isSimple(G
));
603 CombinatorialEmbedding
E(G
);
605 OGDF_ASSERT(E
.consistencyCheck());
609 adjEntry adj
, succ
, succ2
, succ3
;
610 NodeArray
<int> marked(E
.getGraph(), 0);
612 forall_nodes(v
,E
.getGraph()) {
613 marked
.init(E
.getGraph(), 0);
616 marked
[adj
->twinNode()] = 1;
619 // forall faces adj to v
621 succ
= adj
->faceCycleSucc();
622 succ2
= succ
->faceCycleSucc();
624 if (succ
->twinNode() != v
&& adj
->twinNode() != v
) {
625 while (succ2
->twinNode() != v
) {
626 if (marked
[succ2
->theNode()] == 1) {
628 succ3
= succ2
->faceCycleSucc();
629 E
.splitFace(succ
, succ3
);
633 e
= E
.splitFace(adj
, succ2
);
634 marked
[succ2
->theNode()] = 1;
636 // old adj is in wrong face
637 adj
= e
->adjSource();
639 succ
= adj
->faceCycleSucc();
640 succ2
= succ
->faceCycleSucc();
648 //--------------------------------------------------------------------------
649 // isAcyclic(), isAcyclicUndirected(), makeAcyclic(), makeAcyclicByReverse()
650 // testing acyclicity, establishing acyclicity
651 //--------------------------------------------------------------------------
652 void dfsIsAcyclic(const Graph
&G
,
654 NodeArray
<int> &number
,
655 NodeArray
<int> &completion
,
659 number
[v
] = ++nNumber
;
662 forall_adj_edges(e
,v
) {
663 node w
= e
->target();
666 dfsIsAcyclic(G
,w
,number
,completion
,nNumber
,nCompletion
);
669 completion
[v
] = ++nCompletion
;
673 void dfsIsAcyclicUndirected(const Graph
&G
,
675 NodeArray
<int> &number
,
677 List
<edge
> &backedges
)
679 number
[v
] = ++nNumber
;
685 if (number
[w
] == 0) {
686 dfsIsAcyclicUndirected(G
,w
,number
,nNumber
,backedges
);
688 if (number
[w
] > number
[v
]) {
689 backedges
.pushBack(adj
->theEdge());
696 bool isAcyclic(const Graph
&G
, List
<edge
> &backedges
)
700 NodeArray
<int> number(G
,0), completion(G
);
701 int nNumber
= 0, nCompletion
= 0;
706 dfsIsAcyclic(G
,v
,number
,completion
,nNumber
,nCompletion
);
710 node src
= e
->source(), tgt
= e
->target();
712 if (number
[src
] >= number
[tgt
] && completion
[src
] <= completion
[tgt
])
713 backedges
.pushBack(e
);
716 return backedges
.empty();
720 bool isAcyclicUndirected(const Graph
&G
, List
<edge
> &backedges
)
724 NodeArray
<int> number(G
,0);
728 if (number
[v
] == 0) {
729 dfsIsAcyclicUndirected(G
,v
,number
,nNumber
,backedges
);
732 return backedges
.empty();
736 void makeAcyclic(Graph
&G
)
738 List
<edge
> backedges
;
739 isAcyclic(G
,backedges
);
741 ListIterator
<edge
> it
;
742 for(it
= backedges
.begin(); it
.valid(); ++it
)
747 void makeAcyclicByReverse(Graph
&G
)
749 List
<edge
> backedges
;
750 isAcyclic(G
,backedges
);
752 ListIterator
<edge
> it
;
753 for(it
= backedges
.begin(); it
.valid(); ++it
)
754 if (!(*it
)->isSelfLoop()) G
.reverseEdge(*it
);
758 //---------------------------------------------------------
759 // hasSingleSource(), hasSingleSink()
760 // testing for single source/sink
761 //---------------------------------------------------------
762 bool hasSingleSource(const Graph
& G
, node
&s
)
768 if (v
->indeg() == 0) {
775 return (G
.empty() || s
!= 0);
779 bool hasSingleSink(const Graph
& G
, node
&t
)
785 if (v
->outdeg() == 0) {
792 return (G
.empty() || t
!= 0);
796 //---------------------------------------------------------
798 // true <=> G is st-graph, i.e., is acyclic, contains exactly one source s
799 // and one sink t, and the edge (s,t); returns single source s and single
800 // sink t if contained (otherwise they are set to 0), and edge st if
801 // contained (otherwise 0)
802 //---------------------------------------------------------
803 bool isStGraph(const Graph
&G
, node
&s
, node
&t
, edge
&st
)
807 hasSingleSource(G
,s
);
810 if (s
== 0 || t
== 0 || isAcyclic(G
) == false) {
816 forall_adj_edges(e
,s
) {
817 if (e
->target() == t
) {
827 //---------------------------------------------------------
828 // topologicalNumbering()
829 // computes a topological numbering of an acyclic graph
830 //---------------------------------------------------------
832 void topologicalNumbering(const Graph
&G
, NodeArray
<int> &num
)
834 BoundedStack
<node
> S(G
.numberOfNodes());
835 NodeArray
<int> indeg(G
);
839 if((indeg
[v
] = v
->indeg()) == 0)
848 forall_adj_edges(e
,v
) {
849 node u
= e
->target();
859 //---------------------------------------------------------
860 // strongComponents()
861 // computes the strongly connected components
862 //---------------------------------------------------------
864 //! Computes the strongly connected components with the algorithm of Tarjan.
866 * @param G is the input graph.
867 * @param w is the current node.
868 * @param S is the stack containing all vertices of the current
869 * component during the algorithm
870 * @param pre is the preorder number.
871 * @param low is the lowest reachable preorder number (lowpoint).
872 * @param cnt is the counter for the dfs-number.
873 * @param scnt is the counter for the components.
874 * @param component is assigned a mapping from nodes to component numbers.
876 void dfsStrongComponents(
879 BoundedStack
<node
>& S
,
884 NodeArray
<int>& component
)
893 forall_adj_edges(e
, w
) {
894 if (e
->source() == w
) {
897 dfsStrongComponents(G
, t
, S
, pre
, low
, cnt
, scnt
, component
);
910 low
[t
] = G
.numberOfNodes();
915 int strongComponents(const Graph
& G
, NodeArray
<int>& component
)
917 if (G
.numberOfNodes() == 0)
919 if (G
.numberOfNodes() == 1){
920 component
[G
.firstNode()] = 0;
923 NodeArray
<int> pre(G
, -1);
924 NodeArray
<int> low(G
, G
.numberOfNodes());
925 BoundedStack
<node
> S(G
.numberOfNodes());
931 dfsStrongComponents(G
, v
, S
, pre
, low
, cnt
, scnt
, component
);
938 //---------------------------------------------------------
940 // testing if graph represents a free forest
941 //---------------------------------------------------------
943 bool isFreeForest(const Graph
&G
)
945 NodeArray
<bool> visited(G
,false);
948 forall_nodes(vFirst
,G
)
950 if(visited
[vFirst
]) continue;
952 StackPure
<Tuple2
<node
,node
> > S
;
953 S
.push(Tuple2
<node
,node
>(vFirst
,0));
957 Tuple2
<node
,node
> t
= S
.pop();
959 node parent
= t
.x2();
966 node w
= adj
->twinNode();
968 // skip edge to parent, but only once!
974 if(visited
[w
] == true)
977 S
.push(Tuple2
<node
,node
>(w
,v
));
986 //---------------------------------------------------------
987 // isForest(), isTree()
988 // testing if graph represents a forest/tree
989 //---------------------------------------------------------
990 static bool dfsIsForest (node v
,
991 NodeArray
<bool> &visited
,
992 NodeArray
<bool> &mark
)
994 SListPure
<node
> sons
;
999 forall_adj_edges(e
,v
) {
1000 node w
= e
->target();
1001 if (w
!= v
&& !mark
[w
]) {
1007 SListIterator
<node
> it
;
1008 for(it
= sons
.begin(); it
.valid(); ++it
)
1011 while(!sons
.empty()) {
1012 node w
= sons
.front();
1015 if (visited
[w
] || dfsIsForest(w
,visited
,mark
) == false)
1022 bool isForest(const Graph
& G
, List
<node
> &roots
)
1025 if (G
.empty()) return true;
1027 NodeArray
<bool> visited(G
,false), mark(G
,false);
1031 if (v
->indeg() == 0) {
1033 if (dfsIsForest(v
,visited
,mark
) == false)
1038 if (!visited
[v
]) return false;
1044 bool isTree (const Graph
& G
, node
&root
)
1048 if (isForest(G
,roots
) && roots
.size() == 1) {
1049 root
= roots
.front(); return true;
1056 } // end namespace ogdf