1 /** \file
2  * \brief Declaration of class StaticSPQRTree
3  *
4  * \author Carsten Gutwenger
5  *
6  * \par License:
7  * This file is part of the Open Graph Drawing Framework (OGDF).
8  *
9  * \par
10  * Copyright (C)<br>
11  * See README.md in the OGDF root directory for details.
12  *
13  * \par
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * Version 2 or 3 as published by the Free Software Foundation;
17  * see the file LICENSE.txt included in the packaging of this file
18  * for details.
19  *
20  * \par
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * \par
27  * You should have received a copy of the GNU General Public
28  * License along with this program; if not, see
29  * http://www.gnu.org/copyleft/gpl.html
30  */
31 
32 #pragma once
33 
34 #include <ogdf/decomposition/SPQRTree.h>
35 #include <ogdf/decomposition/StaticSkeleton.h>
36 #include <ogdf/graphalg/Triconnectivity.h>
37 
38 namespace ogdf {
39 
40 /**
41  * \brief Linear-time implementation of static SPQR-trees.
42  *
43  * @ingroup decomp
44  *
45  * The class StaticSPQRTree maintains the arrangement of the triconnected
46  * components of a biconnected multi-graph \a G [Hopcroft, Tarjan 1973]
47  * as a so-called SPQR tree \a T [Fi Battista, Tamassia, 1996]. We
48  * call \a G the original graph of \a T.
49  * The class StaticSPQRTree supports only the statical construction
50  * of an SPQR-tree for a given graph \a G, dynamic updates are
51  * not supported.
52  *
53  * Each node of the tree has an associated type (represented by
54  * SPQRTree::NodeType), which is either SNode, PNode, or
55  * RNode, and a skeleton (represented by the class StaticSkeleton).
56  * The skeletons of the nodes of \a T are in one-to-one
57  * correspondence to the triconnected components of \a G, i.e.,
58  * S-nodes correspond to polygons, P-nodes to bonds, and
59  * R-nodes to triconnected graphs.
60  *
61  * In our representation of SPQR-trees, Q-nodes are omitted. Instead,
62  * the skeleton S of a node \a v in \a T contains two types of edges:
63  * real edges, which correspond to edges in \a G, and virtual edges, which
64  * correspond to edges in \a T having \a v as an endpoint.
65  * There is a special edge \a er in G at which \a T is rooted, i.e., the
66  * root node of \a T is the node whose skeleton contains the real edge
67  * corresponding to \a er.
68  *
69  * The reference edge of the skeleton of the root node is \a er, the
70  * reference edge of the skeleton \a S of a non-root node \a v is the virtual
71  * edge in \a S that corresponds to the tree edge (parent(\a v),\a v).
72  */
73 class OGDF_EXPORT StaticSPQRTree : public virtual SPQRTree
74 {
75 public:
76 	friend class StaticSkeleton;
77 
78 	// constructors
79 
80 	/**
81 	 * \brief Creates an SPQR tree \a T for graph \p G rooted at the first edge of \p G.
82 	 * \pre \p G is biconnected and contains at least 3 nodes,
83 	 *      or \p G has exactly 2 nodes and at least 3 edges.
84 	 */
StaticSPQRTree(const Graph & G)85 	explicit StaticSPQRTree(const Graph &G) : m_skOf(G), m_copyOf(G) { OGDF_ASSERT(G.numberOfEdges() > 0); m_pGraph = &G; init(G.firstEdge()); }
86 
87 	/**
88 	 * \brief Creates an SPQR tree \a T for graph \p G rooted at the edge \p e.
89 	 * \pre \p e is in \p G, \p G is biconnected and contains at least 3 nodes,
90 	 *      or \p G has exactly 2 nodes and at least 3 edges.
91 	 */
StaticSPQRTree(const Graph & G,edge e)92 	StaticSPQRTree(const Graph &G, edge e) : m_skOf(G), m_copyOf(G) { m_pGraph = &G; init(e); }
93 
94 	/**
95 	 * \brief Creates an SPQR tree \a T for graph \p G rooted at the first edge of \p G.
96 	 * \pre \p G is biconnected and contains at least 3 nodes,
97 	 *      or \p G has exactly 2 nodes and at least 3 edges.
98 	 */
StaticSPQRTree(const Graph & G,Triconnectivity & tricComp)99 	StaticSPQRTree(const Graph &G, Triconnectivity &tricComp) : m_skOf(G), m_copyOf(G) { m_pGraph = &G; init(G.firstEdge(),tricComp); }
100 
101 	//! Destructor.
102 	~StaticSPQRTree();
103 
104 	//! \name Access operations
105 	//! @{
106 
107 	//! Returns a reference to the original graph \a G.
originalGraph()108 	const Graph &originalGraph() const override { return *m_pGraph; }
109 
110 	//! Returns a reference to the tree \a T.
tree()111 	const Graph &tree() const override { return m_tree; }
112 
113 	//! Returns the edge of \a G at which \a T is rooted.
rootEdge()114 	edge rootEdge() const override { return m_rootEdge; }
115 
116 	//! Returns the root node of \a T.
rootNode()117 	node rootNode() const override { return m_rootNode; }
118 
119 	//! Returns the number of S-nodes in \a T.
numberOfSNodes()120 	int numberOfSNodes() const override { return m_numS; }
121 
122 	//! Returns the number of P-nodes in \a T.
numberOfPNodes()123 	int numberOfPNodes() const override { return m_numP; }
124 
125 	//! Returns the number of R-nodes in \a T.
numberOfRNodes()126 	int numberOfRNodes() const override { return m_numR; }
127 
128 	/**
129 	 * \brief Returns the type of node \p v.
130 	 * \pre \p v is a node in \a T
131 	 */
typeOf(node v)132 	NodeType typeOf(node v) const override { return m_type[v]; }
133 
134 	//! Returns the list of all nodes with type \p t.
135 	List<node> nodesOfType(NodeType t) const override;
136 
137 	/**
138 	 * \brief Returns the skeleton of node \p v.
139 	 * \pre \p v is a node in \a T
140 	 */
skeleton(node v)141 	Skeleton &skeleton(node v) const override { return *m_sk[v]; }
142 
143 	/**
144 	 * \brief Returns the edge in skeleton of source(\p e) that corresponds to tree edge \p e.
145 	 * \pre \p e is an edge in \a T
146 	 */
skeletonEdgeSrc(edge e)147 	edge skeletonEdgeSrc(edge e) const { return m_skEdgeSrc[e]; }
148 
149 	/**
150 	 * \brief Returns the edge in skeleton of target(\p e) that corresponds to tree edge \p e.
151 	 * \pre \p e is an edge in \a T
152 	 */
skeletonEdgeTgt(edge e)153 	edge skeletonEdgeTgt(edge e) const { return m_skEdgeTgt[e]; }
154 
155 	/**
156 	 * \brief Returns the skeleton that contains the real edge \p e.
157 	 * \pre \p e is an edge in \a G
158 	 */
skeletonOfReal(edge e)159 	const Skeleton &skeletonOfReal(edge e) const override { return *m_skOf[e]; }
160 
161 	/**
162 	 * \brief Returns the skeleton edge that corresponds to the real edge \p e.
163 	 * \pre \p e is an edge in \a G
164 	 */
copyOfReal(edge e)165 	edge copyOfReal(edge e) const override { return m_copyOf[e]; }
166 
167 	//! @}
168 	//! \name Update operations
169 	//! @{
170 
171 	/**
172 	 * \brief Roots \a T at edge \p e and returns the new root node of \a T.
173 	 * \pre \p e is an edge in \a G
174 	 */
175 	node rootTreeAt(edge e) override;
176 
177 	/**
178 	 * \brief Roots \a T at node \p v and returns \p v.
179 	 * \pre \p v is a node in \a T
180 	 */
181 	node rootTreeAt(node v) override;
182 
183 	//! @}
184 
185 protected:
186 
187 	//! Initialization (called by constructor).
188 	void init(edge e);
189 
190 	//! Initialization (called by constructor).
191 	void init(edge eRef, Triconnectivity &tricComp);
192 
193 	//! Recursively performs rooting of tree.
194 	void rootRec(node v, edge ef);
195 
196 	/**
197 	 * \brief Recursively performs the task of adding edges (and nodes)
198 	 * to the pertinent graph \p Gp for each involved skeleton graph.
199 	 */
cpRec(node v,PertinentGraph & Gp)200 	void cpRec(node v, PertinentGraph &Gp) const override
201 	{
202 		const Skeleton &S = skeleton(v);
203 
204 		for(edge e : S.getGraph().edges) {
205 			edge eOrig = S.realEdge(e);
206 			if (eOrig != nullptr) cpAddEdge(eOrig,Gp);
207 		}
208 
209 		for(adjEntry adj : v->adjEntries) {
210 			node w = adj->theEdge()->target();
211 			if (w != v) cpRec(w,Gp);
212 		}
213 	}
214 
215 
216 	const Graph *m_pGraph;  //!< pointer to original graph
217 	Graph        m_tree;    //!< underlying tree graph
218 
219 	edge m_rootEdge;  //!< edge of \a G at which \a T is rooted
220 	node m_rootNode;  //!< root node of \a T
221 
222 	int m_numS;  //!< number of S-nodes
223 	int m_numP;  //!< number of P-nodes
224 	int m_numR;  //!< number of R-nodes
225 
226 	NodeArray<NodeType> m_type;  //!< type of nodes in \a T
227 
228 	NodeArray<StaticSkeleton *> m_sk;         //!< pointer to skeleton of a node in \a T
229 	EdgeArray<edge>             m_skEdgeSrc;  //!< corresponding edge in skeleton(source(\a e))
230 	EdgeArray<edge>             m_skEdgeTgt;  //!< corresponding edge in skeleton(target(\a e))
231 
232 	EdgeArray<StaticSkeleton *> m_skOf;    //!< skeleton containing real edge \a e
233 	EdgeArray<edge>             m_copyOf;  //!< skeleton edge corresponding to real edge \a e
234 };
235 
236 }
237