lemongraph 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +8 -0
- data/LICENSE +674 -0
- data/README.md +6 -0
- data/ext/lemon-1.3.1/AUTHORS +26 -0
- data/ext/lemon-1.3.1/CMakeLists.txt +371 -0
- data/ext/lemon-1.3.1/INSTALL +167 -0
- data/ext/lemon-1.3.1/LICENSE +32 -0
- data/ext/lemon-1.3.1/NEWS +337 -0
- data/ext/lemon-1.3.1/README +50 -0
- data/ext/lemon-1.3.1/cmake/FindCOIN.cmake +110 -0
- data/ext/lemon-1.3.1/cmake/FindGLPK.cmake +55 -0
- data/ext/lemon-1.3.1/cmake/FindGhostscript.cmake +10 -0
- data/ext/lemon-1.3.1/cmake/FindILOG.cmake +102 -0
- data/ext/lemon-1.3.1/cmake/FindSOPLEX.cmake +23 -0
- data/ext/lemon-1.3.1/cmake/LEMONConfig.cmake.in +13 -0
- data/ext/lemon-1.3.1/cmake/nsis/lemon.ico +0 -0
- data/ext/lemon-1.3.1/cmake/nsis/uninstall.ico +0 -0
- data/ext/lemon-1.3.1/cmake/version.cmake +1 -0
- data/ext/lemon-1.3.1/cmake/version.cmake.in +1 -0
- data/ext/lemon-1.3.1/contrib/CMakeLists.txt +19 -0
- data/ext/lemon-1.3.1/lemon/CMakeLists.txt +91 -0
- data/ext/lemon-1.3.1/lemon/adaptors.h +3638 -0
- data/ext/lemon-1.3.1/lemon/arg_parser.cc +474 -0
- data/ext/lemon-1.3.1/lemon/arg_parser.h +440 -0
- data/ext/lemon-1.3.1/lemon/assert.h +214 -0
- data/ext/lemon-1.3.1/lemon/base.cc +37 -0
- data/ext/lemon-1.3.1/lemon/bellman_ford.h +1116 -0
- data/ext/lemon-1.3.1/lemon/bfs.h +1754 -0
- data/ext/lemon-1.3.1/lemon/bin_heap.h +347 -0
- data/ext/lemon-1.3.1/lemon/binomial_heap.h +445 -0
- data/ext/lemon-1.3.1/lemon/bits/alteration_notifier.h +472 -0
- data/ext/lemon-1.3.1/lemon/bits/array_map.h +351 -0
- data/ext/lemon-1.3.1/lemon/bits/bezier.h +174 -0
- data/ext/lemon-1.3.1/lemon/bits/default_map.h +182 -0
- data/ext/lemon-1.3.1/lemon/bits/edge_set_extender.h +627 -0
- data/ext/lemon-1.3.1/lemon/bits/enable_if.h +131 -0
- data/ext/lemon-1.3.1/lemon/bits/graph_adaptor_extender.h +401 -0
- data/ext/lemon-1.3.1/lemon/bits/graph_extender.h +1332 -0
- data/ext/lemon-1.3.1/lemon/bits/lock.h +65 -0
- data/ext/lemon-1.3.1/lemon/bits/map_extender.h +332 -0
- data/ext/lemon-1.3.1/lemon/bits/path_dump.h +177 -0
- data/ext/lemon-1.3.1/lemon/bits/solver_bits.h +194 -0
- data/ext/lemon-1.3.1/lemon/bits/traits.h +388 -0
- data/ext/lemon-1.3.1/lemon/bits/variant.h +494 -0
- data/ext/lemon-1.3.1/lemon/bits/vector_map.h +244 -0
- data/ext/lemon-1.3.1/lemon/bits/windows.cc +166 -0
- data/ext/lemon-1.3.1/lemon/bits/windows.h +44 -0
- data/ext/lemon-1.3.1/lemon/bucket_heap.h +594 -0
- data/ext/lemon-1.3.1/lemon/capacity_scaling.h +1014 -0
- data/ext/lemon-1.3.1/lemon/cbc.cc +460 -0
- data/ext/lemon-1.3.1/lemon/cbc.h +129 -0
- data/ext/lemon-1.3.1/lemon/christofides_tsp.h +254 -0
- data/ext/lemon-1.3.1/lemon/circulation.h +807 -0
- data/ext/lemon-1.3.1/lemon/clp.cc +464 -0
- data/ext/lemon-1.3.1/lemon/clp.h +164 -0
- data/ext/lemon-1.3.1/lemon/color.cc +44 -0
- data/ext/lemon-1.3.1/lemon/color.h +204 -0
- data/ext/lemon-1.3.1/lemon/concept_check.h +77 -0
- data/ext/lemon-1.3.1/lemon/concepts/bpgraph.h +1029 -0
- data/ext/lemon-1.3.1/lemon/concepts/digraph.h +491 -0
- data/ext/lemon-1.3.1/lemon/concepts/graph.h +788 -0
- data/ext/lemon-1.3.1/lemon/concepts/graph_components.h +2134 -0
- data/ext/lemon-1.3.1/lemon/concepts/heap.h +324 -0
- data/ext/lemon-1.3.1/lemon/concepts/maps.h +223 -0
- data/ext/lemon-1.3.1/lemon/concepts/path.h +312 -0
- data/ext/lemon-1.3.1/lemon/config.h.in +22 -0
- data/ext/lemon-1.3.1/lemon/connectivity.h +1688 -0
- data/ext/lemon-1.3.1/lemon/core.h +2506 -0
- data/ext/lemon-1.3.1/lemon/cost_scaling.h +1607 -0
- data/ext/lemon-1.3.1/lemon/counter.h +249 -0
- data/ext/lemon-1.3.1/lemon/cplex.cc +994 -0
- data/ext/lemon-1.3.1/lemon/cplex.h +292 -0
- data/ext/lemon-1.3.1/lemon/cycle_canceling.h +1230 -0
- data/ext/lemon-1.3.1/lemon/dfs.h +1637 -0
- data/ext/lemon-1.3.1/lemon/dheap.h +352 -0
- data/ext/lemon-1.3.1/lemon/dijkstra.h +1303 -0
- data/ext/lemon-1.3.1/lemon/dim2.h +726 -0
- data/ext/lemon-1.3.1/lemon/dimacs.h +448 -0
- data/ext/lemon-1.3.1/lemon/edge_set.h +1420 -0
- data/ext/lemon-1.3.1/lemon/edmonds_karp.h +556 -0
- data/ext/lemon-1.3.1/lemon/elevator.h +982 -0
- data/ext/lemon-1.3.1/lemon/error.h +276 -0
- data/ext/lemon-1.3.1/lemon/euler.h +287 -0
- data/ext/lemon-1.3.1/lemon/fib_heap.h +475 -0
- data/ext/lemon-1.3.1/lemon/fractional_matching.h +2139 -0
- data/ext/lemon-1.3.1/lemon/full_graph.h +1082 -0
- data/ext/lemon-1.3.1/lemon/glpk.cc +1012 -0
- data/ext/lemon-1.3.1/lemon/glpk.h +263 -0
- data/ext/lemon-1.3.1/lemon/gomory_hu.h +568 -0
- data/ext/lemon-1.3.1/lemon/graph_to_eps.h +1186 -0
- data/ext/lemon-1.3.1/lemon/greedy_tsp.h +251 -0
- data/ext/lemon-1.3.1/lemon/grid_graph.h +699 -0
- data/ext/lemon-1.3.1/lemon/grosso_locatelli_pullan_mc.h +840 -0
- data/ext/lemon-1.3.1/lemon/hao_orlin.h +1015 -0
- data/ext/lemon-1.3.1/lemon/hartmann_orlin_mmc.h +654 -0
- data/ext/lemon-1.3.1/lemon/howard_mmc.h +651 -0
- data/ext/lemon-1.3.1/lemon/hypercube_graph.h +459 -0
- data/ext/lemon-1.3.1/lemon/insertion_tsp.h +533 -0
- data/ext/lemon-1.3.1/lemon/karp_mmc.h +590 -0
- data/ext/lemon-1.3.1/lemon/kruskal.h +324 -0
- data/ext/lemon-1.3.1/lemon/lemon.pc.in +10 -0
- data/ext/lemon-1.3.1/lemon/lgf_reader.h +3854 -0
- data/ext/lemon-1.3.1/lemon/lgf_writer.h +2687 -0
- data/ext/lemon-1.3.1/lemon/list_graph.h +2510 -0
- data/ext/lemon-1.3.1/lemon/lp.h +95 -0
- data/ext/lemon-1.3.1/lemon/lp_base.cc +30 -0
- data/ext/lemon-1.3.1/lemon/lp_base.h +2147 -0
- data/ext/lemon-1.3.1/lemon/lp_skeleton.cc +143 -0
- data/ext/lemon-1.3.1/lemon/lp_skeleton.h +234 -0
- data/ext/lemon-1.3.1/lemon/maps.h +4057 -0
- data/ext/lemon-1.3.1/lemon/matching.h +3505 -0
- data/ext/lemon-1.3.1/lemon/math.h +77 -0
- data/ext/lemon-1.3.1/lemon/max_cardinality_search.h +794 -0
- data/ext/lemon-1.3.1/lemon/min_cost_arborescence.h +808 -0
- data/ext/lemon-1.3.1/lemon/nagamochi_ibaraki.h +702 -0
- data/ext/lemon-1.3.1/lemon/nauty_reader.h +113 -0
- data/ext/lemon-1.3.1/lemon/nearest_neighbor_tsp.h +238 -0
- data/ext/lemon-1.3.1/lemon/network_simplex.h +1659 -0
- data/ext/lemon-1.3.1/lemon/opt2_tsp.h +367 -0
- data/ext/lemon-1.3.1/lemon/pairing_heap.h +474 -0
- data/ext/lemon-1.3.1/lemon/path.h +1164 -0
- data/ext/lemon-1.3.1/lemon/planarity.h +2754 -0
- data/ext/lemon-1.3.1/lemon/preflow.h +985 -0
- data/ext/lemon-1.3.1/lemon/quad_heap.h +343 -0
- data/ext/lemon-1.3.1/lemon/radix_heap.h +438 -0
- data/ext/lemon-1.3.1/lemon/radix_sort.h +487 -0
- data/ext/lemon-1.3.1/lemon/random.cc +29 -0
- data/ext/lemon-1.3.1/lemon/random.h +1005 -0
- data/ext/lemon-1.3.1/lemon/smart_graph.h +1344 -0
- data/ext/lemon-1.3.1/lemon/soplex.cc +465 -0
- data/ext/lemon-1.3.1/lemon/soplex.h +158 -0
- data/ext/lemon-1.3.1/lemon/static_graph.h +476 -0
- data/ext/lemon-1.3.1/lemon/suurballe.h +776 -0
- data/ext/lemon-1.3.1/lemon/time_measure.h +610 -0
- data/ext/lemon-1.3.1/lemon/tolerance.h +242 -0
- data/ext/lemon-1.3.1/lemon/unionfind.h +1824 -0
- data/ext/lemon-1.3.1/scripts/unify-sources.sh +390 -0
- data/ext/lemon-1.3.1/scripts/valgrind-wrapper.sh +22 -0
- data/ext/lemongraph/arc_map.cc +1007 -0
- data/ext/lemongraph/digraph.cc +282 -0
- data/ext/lemongraph/digraph_arc.cc +153 -0
- data/ext/lemongraph/digraph_node.cc +277 -0
- data/ext/lemongraph/edge_map.cc +770 -0
- data/ext/lemongraph/extconf.rb +53 -0
- data/ext/lemongraph/graph.cc +351 -0
- data/ext/lemongraph/graph_arc.cc +95 -0
- data/ext/lemongraph/graph_edge.cc +153 -0
- data/ext/lemongraph/graph_item.cc +76 -0
- data/ext/lemongraph/graph_node.cc +321 -0
- data/ext/lemongraph/lemongraph.cc +260 -0
- data/ext/lemongraph/lemongraph.hh +295 -0
- data/ext/lemongraph/lemongraph.map +6 -0
- data/ext/lemongraph/lemongraph_export.hh +31 -0
- data/ext/lemongraph/node_map.cc +1011 -0
- data/lemongraph.gemspec +176 -0
- data/lib/lemongraph/graphviz.rb +240 -0
- data/lib/lemongraph/version.rb +4 -0
- data/lib/lemongraph.rb +21 -0
- data/samples/lemondeps.rb +38 -0
- metadata +202 -0
|
@@ -0,0 +1,2754 @@
|
|
|
1
|
+
/* -*- mode: C++; indent-tabs-mode: nil; -*-
|
|
2
|
+
*
|
|
3
|
+
* This file is a part of LEMON, a generic C++ optimization library.
|
|
4
|
+
*
|
|
5
|
+
* Copyright (C) 2003-2013
|
|
6
|
+
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
|
|
7
|
+
* (Egervary Research Group on Combinatorial Optimization, EGRES).
|
|
8
|
+
*
|
|
9
|
+
* Permission to use, modify and distribute this software is granted
|
|
10
|
+
* provided that this copyright notice appears in all copies. For
|
|
11
|
+
* precise terms see the accompanying LICENSE file.
|
|
12
|
+
*
|
|
13
|
+
* This software is provided "AS IS" with no warranty of any kind,
|
|
14
|
+
* express or implied, and with no claim as to its suitability for any
|
|
15
|
+
* purpose.
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
#ifndef LEMON_PLANARITY_H
|
|
20
|
+
#define LEMON_PLANARITY_H
|
|
21
|
+
|
|
22
|
+
/// \ingroup planar
|
|
23
|
+
/// \file
|
|
24
|
+
/// \brief Planarity checking, embedding, drawing and coloring
|
|
25
|
+
|
|
26
|
+
#include <vector>
|
|
27
|
+
#include <list>
|
|
28
|
+
|
|
29
|
+
#include <lemon/dfs.h>
|
|
30
|
+
#include <lemon/bfs.h>
|
|
31
|
+
#include <lemon/radix_sort.h>
|
|
32
|
+
#include <lemon/maps.h>
|
|
33
|
+
#include <lemon/path.h>
|
|
34
|
+
#include <lemon/bucket_heap.h>
|
|
35
|
+
#include <lemon/adaptors.h>
|
|
36
|
+
#include <lemon/edge_set.h>
|
|
37
|
+
#include <lemon/color.h>
|
|
38
|
+
#include <lemon/dim2.h>
|
|
39
|
+
|
|
40
|
+
namespace lemon {
|
|
41
|
+
|
|
42
|
+
namespace _planarity_bits {
|
|
43
|
+
|
|
44
|
+
template <typename Graph>
|
|
45
|
+
struct PlanarityVisitor : DfsVisitor<Graph> {
|
|
46
|
+
|
|
47
|
+
TEMPLATE_GRAPH_TYPEDEFS(Graph);
|
|
48
|
+
|
|
49
|
+
typedef typename Graph::template NodeMap<Arc> PredMap;
|
|
50
|
+
|
|
51
|
+
typedef typename Graph::template EdgeMap<bool> TreeMap;
|
|
52
|
+
|
|
53
|
+
typedef typename Graph::template NodeMap<int> OrderMap;
|
|
54
|
+
typedef std::vector<Node> OrderList;
|
|
55
|
+
|
|
56
|
+
typedef typename Graph::template NodeMap<int> LowMap;
|
|
57
|
+
typedef typename Graph::template NodeMap<int> AncestorMap;
|
|
58
|
+
|
|
59
|
+
PlanarityVisitor(const Graph& graph,
|
|
60
|
+
PredMap& pred_map, TreeMap& tree_map,
|
|
61
|
+
OrderMap& order_map, OrderList& order_list,
|
|
62
|
+
AncestorMap& ancestor_map, LowMap& low_map)
|
|
63
|
+
: _graph(graph), _pred_map(pred_map), _tree_map(tree_map),
|
|
64
|
+
_order_map(order_map), _order_list(order_list),
|
|
65
|
+
_ancestor_map(ancestor_map), _low_map(low_map) {}
|
|
66
|
+
|
|
67
|
+
void reach(const Node& node) {
|
|
68
|
+
_order_map[node] = _order_list.size();
|
|
69
|
+
_low_map[node] = _order_list.size();
|
|
70
|
+
_ancestor_map[node] = _order_list.size();
|
|
71
|
+
_order_list.push_back(node);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
void discover(const Arc& arc) {
|
|
75
|
+
Node target = _graph.target(arc);
|
|
76
|
+
|
|
77
|
+
_tree_map[arc] = true;
|
|
78
|
+
_pred_map[target] = arc;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
void examine(const Arc& arc) {
|
|
82
|
+
Node source = _graph.source(arc);
|
|
83
|
+
Node target = _graph.target(arc);
|
|
84
|
+
|
|
85
|
+
if (_order_map[target] < _order_map[source] && !_tree_map[arc]) {
|
|
86
|
+
if (_low_map[source] > _order_map[target]) {
|
|
87
|
+
_low_map[source] = _order_map[target];
|
|
88
|
+
}
|
|
89
|
+
if (_ancestor_map[source] > _order_map[target]) {
|
|
90
|
+
_ancestor_map[source] = _order_map[target];
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
void backtrack(const Arc& arc) {
|
|
96
|
+
Node source = _graph.source(arc);
|
|
97
|
+
Node target = _graph.target(arc);
|
|
98
|
+
|
|
99
|
+
if (_low_map[source] > _low_map[target]) {
|
|
100
|
+
_low_map[source] = _low_map[target];
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const Graph& _graph;
|
|
105
|
+
PredMap& _pred_map;
|
|
106
|
+
TreeMap& _tree_map;
|
|
107
|
+
OrderMap& _order_map;
|
|
108
|
+
OrderList& _order_list;
|
|
109
|
+
AncestorMap& _ancestor_map;
|
|
110
|
+
LowMap& _low_map;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
template <typename Graph, bool embedding = true>
|
|
114
|
+
struct NodeDataNode {
|
|
115
|
+
int prev, next;
|
|
116
|
+
int visited;
|
|
117
|
+
typename Graph::Arc first;
|
|
118
|
+
bool inverted;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
template <typename Graph>
|
|
122
|
+
struct NodeDataNode<Graph, false> {
|
|
123
|
+
int prev, next;
|
|
124
|
+
int visited;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
template <typename Graph>
|
|
128
|
+
struct ChildListNode {
|
|
129
|
+
typedef typename Graph::Node Node;
|
|
130
|
+
Node first;
|
|
131
|
+
Node prev, next;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
template <typename Graph>
|
|
135
|
+
struct ArcListNode {
|
|
136
|
+
typename Graph::Arc prev, next;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
template <typename Graph>
|
|
140
|
+
class PlanarityChecking {
|
|
141
|
+
private:
|
|
142
|
+
|
|
143
|
+
TEMPLATE_GRAPH_TYPEDEFS(Graph);
|
|
144
|
+
|
|
145
|
+
const Graph& _graph;
|
|
146
|
+
|
|
147
|
+
private:
|
|
148
|
+
|
|
149
|
+
typedef typename Graph::template NodeMap<Arc> PredMap;
|
|
150
|
+
|
|
151
|
+
typedef typename Graph::template EdgeMap<bool> TreeMap;
|
|
152
|
+
|
|
153
|
+
typedef typename Graph::template NodeMap<int> OrderMap;
|
|
154
|
+
typedef std::vector<Node> OrderList;
|
|
155
|
+
|
|
156
|
+
typedef typename Graph::template NodeMap<int> LowMap;
|
|
157
|
+
typedef typename Graph::template NodeMap<int> AncestorMap;
|
|
158
|
+
|
|
159
|
+
typedef _planarity_bits::NodeDataNode<Graph> NodeDataNode;
|
|
160
|
+
typedef std::vector<NodeDataNode> NodeData;
|
|
161
|
+
|
|
162
|
+
typedef _planarity_bits::ChildListNode<Graph> ChildListNode;
|
|
163
|
+
typedef typename Graph::template NodeMap<ChildListNode> ChildLists;
|
|
164
|
+
|
|
165
|
+
typedef typename Graph::template NodeMap<std::list<int> > MergeRoots;
|
|
166
|
+
|
|
167
|
+
typedef typename Graph::template NodeMap<bool> EmbedArc;
|
|
168
|
+
|
|
169
|
+
public:
|
|
170
|
+
|
|
171
|
+
PlanarityChecking(const Graph& graph) : _graph(graph) {}
|
|
172
|
+
|
|
173
|
+
bool run() {
|
|
174
|
+
typedef _planarity_bits::PlanarityVisitor<Graph> Visitor;
|
|
175
|
+
|
|
176
|
+
PredMap pred_map(_graph, INVALID);
|
|
177
|
+
TreeMap tree_map(_graph, false);
|
|
178
|
+
|
|
179
|
+
OrderMap order_map(_graph, -1);
|
|
180
|
+
OrderList order_list;
|
|
181
|
+
|
|
182
|
+
AncestorMap ancestor_map(_graph, -1);
|
|
183
|
+
LowMap low_map(_graph, -1);
|
|
184
|
+
|
|
185
|
+
Visitor visitor(_graph, pred_map, tree_map,
|
|
186
|
+
order_map, order_list, ancestor_map, low_map);
|
|
187
|
+
DfsVisit<Graph, Visitor> visit(_graph, visitor);
|
|
188
|
+
visit.run();
|
|
189
|
+
|
|
190
|
+
ChildLists child_lists(_graph);
|
|
191
|
+
createChildLists(tree_map, order_map, low_map, child_lists);
|
|
192
|
+
|
|
193
|
+
NodeData node_data(2 * order_list.size());
|
|
194
|
+
|
|
195
|
+
EmbedArc embed_arc(_graph, false);
|
|
196
|
+
|
|
197
|
+
MergeRoots merge_roots(_graph);
|
|
198
|
+
|
|
199
|
+
for (int i = order_list.size() - 1; i >= 0; --i) {
|
|
200
|
+
|
|
201
|
+
Node node = order_list[i];
|
|
202
|
+
|
|
203
|
+
Node source = node;
|
|
204
|
+
for (OutArcIt e(_graph, node); e != INVALID; ++e) {
|
|
205
|
+
Node target = _graph.target(e);
|
|
206
|
+
|
|
207
|
+
if (order_map[source] < order_map[target] && tree_map[e]) {
|
|
208
|
+
initFace(target, node_data, order_map, order_list);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
for (OutArcIt e(_graph, node); e != INVALID; ++e) {
|
|
213
|
+
Node target = _graph.target(e);
|
|
214
|
+
|
|
215
|
+
if (order_map[source] < order_map[target] && !tree_map[e]) {
|
|
216
|
+
embed_arc[target] = true;
|
|
217
|
+
walkUp(target, source, i, pred_map, low_map,
|
|
218
|
+
order_map, order_list, node_data, merge_roots);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
for (typename MergeRoots::Value::iterator it =
|
|
223
|
+
merge_roots[node].begin();
|
|
224
|
+
it != merge_roots[node].end(); ++it) {
|
|
225
|
+
int rn = *it;
|
|
226
|
+
walkDown(rn, i, node_data, order_list, child_lists,
|
|
227
|
+
ancestor_map, low_map, embed_arc, merge_roots);
|
|
228
|
+
}
|
|
229
|
+
merge_roots[node].clear();
|
|
230
|
+
|
|
231
|
+
for (OutArcIt e(_graph, node); e != INVALID; ++e) {
|
|
232
|
+
Node target = _graph.target(e);
|
|
233
|
+
|
|
234
|
+
if (order_map[source] < order_map[target] && !tree_map[e]) {
|
|
235
|
+
if (embed_arc[target]) {
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
private:
|
|
246
|
+
|
|
247
|
+
void createChildLists(const TreeMap& tree_map, const OrderMap& order_map,
|
|
248
|
+
const LowMap& low_map, ChildLists& child_lists) {
|
|
249
|
+
|
|
250
|
+
for (NodeIt n(_graph); n != INVALID; ++n) {
|
|
251
|
+
Node source = n;
|
|
252
|
+
|
|
253
|
+
std::vector<Node> targets;
|
|
254
|
+
for (OutArcIt e(_graph, n); e != INVALID; ++e) {
|
|
255
|
+
Node target = _graph.target(e);
|
|
256
|
+
|
|
257
|
+
if (order_map[source] < order_map[target] && tree_map[e]) {
|
|
258
|
+
targets.push_back(target);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (targets.size() == 0) {
|
|
263
|
+
child_lists[source].first = INVALID;
|
|
264
|
+
} else if (targets.size() == 1) {
|
|
265
|
+
child_lists[source].first = targets[0];
|
|
266
|
+
child_lists[targets[0]].prev = INVALID;
|
|
267
|
+
child_lists[targets[0]].next = INVALID;
|
|
268
|
+
} else {
|
|
269
|
+
radixSort(targets.begin(), targets.end(), mapToFunctor(low_map));
|
|
270
|
+
for (int i = 1; i < int(targets.size()); ++i) {
|
|
271
|
+
child_lists[targets[i]].prev = targets[i - 1];
|
|
272
|
+
child_lists[targets[i - 1]].next = targets[i];
|
|
273
|
+
}
|
|
274
|
+
child_lists[targets.back()].next = INVALID;
|
|
275
|
+
child_lists[targets.front()].prev = INVALID;
|
|
276
|
+
child_lists[source].first = targets.front();
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
void walkUp(const Node& node, Node root, int rorder,
|
|
282
|
+
const PredMap& pred_map, const LowMap& low_map,
|
|
283
|
+
const OrderMap& order_map, const OrderList& order_list,
|
|
284
|
+
NodeData& node_data, MergeRoots& merge_roots) {
|
|
285
|
+
|
|
286
|
+
int na, nb;
|
|
287
|
+
bool da, db;
|
|
288
|
+
|
|
289
|
+
na = nb = order_map[node];
|
|
290
|
+
da = true; db = false;
|
|
291
|
+
|
|
292
|
+
while (true) {
|
|
293
|
+
|
|
294
|
+
if (node_data[na].visited == rorder) break;
|
|
295
|
+
if (node_data[nb].visited == rorder) break;
|
|
296
|
+
|
|
297
|
+
node_data[na].visited = rorder;
|
|
298
|
+
node_data[nb].visited = rorder;
|
|
299
|
+
|
|
300
|
+
int rn = -1;
|
|
301
|
+
|
|
302
|
+
if (na >= int(order_list.size())) {
|
|
303
|
+
rn = na;
|
|
304
|
+
} else if (nb >= int(order_list.size())) {
|
|
305
|
+
rn = nb;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (rn == -1) {
|
|
309
|
+
int nn;
|
|
310
|
+
|
|
311
|
+
nn = da ? node_data[na].prev : node_data[na].next;
|
|
312
|
+
da = node_data[nn].prev != na;
|
|
313
|
+
na = nn;
|
|
314
|
+
|
|
315
|
+
nn = db ? node_data[nb].prev : node_data[nb].next;
|
|
316
|
+
db = node_data[nn].prev != nb;
|
|
317
|
+
nb = nn;
|
|
318
|
+
|
|
319
|
+
} else {
|
|
320
|
+
|
|
321
|
+
Node rep = order_list[rn - order_list.size()];
|
|
322
|
+
Node parent = _graph.source(pred_map[rep]);
|
|
323
|
+
|
|
324
|
+
if (low_map[rep] < rorder) {
|
|
325
|
+
merge_roots[parent].push_back(rn);
|
|
326
|
+
} else {
|
|
327
|
+
merge_roots[parent].push_front(rn);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (parent != root) {
|
|
331
|
+
na = nb = order_map[parent];
|
|
332
|
+
da = true; db = false;
|
|
333
|
+
} else {
|
|
334
|
+
break;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
void walkDown(int rn, int rorder, NodeData& node_data,
|
|
341
|
+
OrderList& order_list, ChildLists& child_lists,
|
|
342
|
+
AncestorMap& ancestor_map, LowMap& low_map,
|
|
343
|
+
EmbedArc& embed_arc, MergeRoots& merge_roots) {
|
|
344
|
+
|
|
345
|
+
std::vector<std::pair<int, bool> > merge_stack;
|
|
346
|
+
|
|
347
|
+
for (int di = 0; di < 2; ++di) {
|
|
348
|
+
bool rd = di == 0;
|
|
349
|
+
int pn = rn;
|
|
350
|
+
int n = rd ? node_data[rn].next : node_data[rn].prev;
|
|
351
|
+
|
|
352
|
+
while (n != rn) {
|
|
353
|
+
|
|
354
|
+
Node node = order_list[n];
|
|
355
|
+
|
|
356
|
+
if (embed_arc[node]) {
|
|
357
|
+
|
|
358
|
+
// Merging components on the critical path
|
|
359
|
+
while (!merge_stack.empty()) {
|
|
360
|
+
|
|
361
|
+
// Component root
|
|
362
|
+
int cn = merge_stack.back().first;
|
|
363
|
+
bool cd = merge_stack.back().second;
|
|
364
|
+
merge_stack.pop_back();
|
|
365
|
+
|
|
366
|
+
// Parent of component
|
|
367
|
+
int dn = merge_stack.back().first;
|
|
368
|
+
bool dd = merge_stack.back().second;
|
|
369
|
+
merge_stack.pop_back();
|
|
370
|
+
|
|
371
|
+
Node parent = order_list[dn];
|
|
372
|
+
|
|
373
|
+
// Erasing from merge_roots
|
|
374
|
+
merge_roots[parent].pop_front();
|
|
375
|
+
|
|
376
|
+
Node child = order_list[cn - order_list.size()];
|
|
377
|
+
|
|
378
|
+
// Erasing from child_lists
|
|
379
|
+
if (child_lists[child].prev != INVALID) {
|
|
380
|
+
child_lists[child_lists[child].prev].next =
|
|
381
|
+
child_lists[child].next;
|
|
382
|
+
} else {
|
|
383
|
+
child_lists[parent].first = child_lists[child].next;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
if (child_lists[child].next != INVALID) {
|
|
387
|
+
child_lists[child_lists[child].next].prev =
|
|
388
|
+
child_lists[child].prev;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Merging external faces
|
|
392
|
+
{
|
|
393
|
+
int en = cn;
|
|
394
|
+
cn = cd ? node_data[cn].prev : node_data[cn].next;
|
|
395
|
+
cd = node_data[cn].next == en;
|
|
396
|
+
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (cd) node_data[cn].next = dn; else node_data[cn].prev = dn;
|
|
400
|
+
if (dd) node_data[dn].prev = cn; else node_data[dn].next = cn;
|
|
401
|
+
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
bool d = pn == node_data[n].prev;
|
|
405
|
+
|
|
406
|
+
if (node_data[n].prev == node_data[n].next &&
|
|
407
|
+
node_data[n].inverted) {
|
|
408
|
+
d = !d;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// Embedding arc into external face
|
|
412
|
+
if (rd) node_data[rn].next = n; else node_data[rn].prev = n;
|
|
413
|
+
if (d) node_data[n].prev = rn; else node_data[n].next = rn;
|
|
414
|
+
pn = rn;
|
|
415
|
+
|
|
416
|
+
embed_arc[order_list[n]] = false;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
if (!merge_roots[node].empty()) {
|
|
420
|
+
|
|
421
|
+
bool d = pn == node_data[n].prev;
|
|
422
|
+
|
|
423
|
+
merge_stack.push_back(std::make_pair(n, d));
|
|
424
|
+
|
|
425
|
+
int rn = merge_roots[node].front();
|
|
426
|
+
|
|
427
|
+
int xn = node_data[rn].next;
|
|
428
|
+
Node xnode = order_list[xn];
|
|
429
|
+
|
|
430
|
+
int yn = node_data[rn].prev;
|
|
431
|
+
Node ynode = order_list[yn];
|
|
432
|
+
|
|
433
|
+
bool rd;
|
|
434
|
+
if (!external(xnode, rorder, child_lists,
|
|
435
|
+
ancestor_map, low_map)) {
|
|
436
|
+
rd = true;
|
|
437
|
+
} else if (!external(ynode, rorder, child_lists,
|
|
438
|
+
ancestor_map, low_map)) {
|
|
439
|
+
rd = false;
|
|
440
|
+
} else if (pertinent(xnode, embed_arc, merge_roots)) {
|
|
441
|
+
rd = true;
|
|
442
|
+
} else {
|
|
443
|
+
rd = false;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
merge_stack.push_back(std::make_pair(rn, rd));
|
|
447
|
+
|
|
448
|
+
pn = rn;
|
|
449
|
+
n = rd ? xn : yn;
|
|
450
|
+
|
|
451
|
+
} else if (!external(node, rorder, child_lists,
|
|
452
|
+
ancestor_map, low_map)) {
|
|
453
|
+
int nn = (node_data[n].next != pn ?
|
|
454
|
+
node_data[n].next : node_data[n].prev);
|
|
455
|
+
|
|
456
|
+
bool nd = n == node_data[nn].prev;
|
|
457
|
+
|
|
458
|
+
if (nd) node_data[nn].prev = pn;
|
|
459
|
+
else node_data[nn].next = pn;
|
|
460
|
+
|
|
461
|
+
if (n == node_data[pn].prev) node_data[pn].prev = nn;
|
|
462
|
+
else node_data[pn].next = nn;
|
|
463
|
+
|
|
464
|
+
node_data[nn].inverted =
|
|
465
|
+
(node_data[nn].prev == node_data[nn].next && nd != rd);
|
|
466
|
+
|
|
467
|
+
n = nn;
|
|
468
|
+
}
|
|
469
|
+
else break;
|
|
470
|
+
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
if (!merge_stack.empty() || n == rn) {
|
|
474
|
+
break;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
void initFace(const Node& node, NodeData& node_data,
|
|
480
|
+
const OrderMap& order_map, const OrderList& order_list) {
|
|
481
|
+
int n = order_map[node];
|
|
482
|
+
int rn = n + order_list.size();
|
|
483
|
+
|
|
484
|
+
node_data[n].next = node_data[n].prev = rn;
|
|
485
|
+
node_data[rn].next = node_data[rn].prev = n;
|
|
486
|
+
|
|
487
|
+
node_data[n].visited = order_list.size();
|
|
488
|
+
node_data[rn].visited = order_list.size();
|
|
489
|
+
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
bool external(const Node& node, int rorder,
|
|
493
|
+
ChildLists& child_lists, AncestorMap& ancestor_map,
|
|
494
|
+
LowMap& low_map) {
|
|
495
|
+
Node child = child_lists[node].first;
|
|
496
|
+
|
|
497
|
+
if (child != INVALID) {
|
|
498
|
+
if (low_map[child] < rorder) return true;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
if (ancestor_map[node] < rorder) return true;
|
|
502
|
+
|
|
503
|
+
return false;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
bool pertinent(const Node& node, const EmbedArc& embed_arc,
|
|
507
|
+
const MergeRoots& merge_roots) {
|
|
508
|
+
return !merge_roots[node].empty() || embed_arc[node];
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/// \ingroup planar
|
|
516
|
+
///
|
|
517
|
+
/// \brief Planarity checking of an undirected simple graph
|
|
518
|
+
///
|
|
519
|
+
/// This function implements the Boyer-Myrvold algorithm for
|
|
520
|
+
/// planarity checking of an undirected simple graph. It is a simplified
|
|
521
|
+
/// version of the PlanarEmbedding algorithm class because neither
|
|
522
|
+
/// the embedding nor the Kuratowski subdivisons are computed.
|
|
523
|
+
template <typename GR>
|
|
524
|
+
bool checkPlanarity(const GR& graph) {
|
|
525
|
+
_planarity_bits::PlanarityChecking<GR> pc(graph);
|
|
526
|
+
return pc.run();
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/// \ingroup planar
|
|
530
|
+
///
|
|
531
|
+
/// \brief Planar embedding of an undirected simple graph
|
|
532
|
+
///
|
|
533
|
+
/// This class implements the Boyer-Myrvold algorithm for planar
|
|
534
|
+
/// embedding of an undirected simple graph. The planar embedding is an
|
|
535
|
+
/// ordering of the outgoing edges of the nodes, which is a possible
|
|
536
|
+
/// configuration to draw the graph in the plane. If there is not
|
|
537
|
+
/// such ordering then the graph contains a K<sub>5</sub> (full graph
|
|
538
|
+
/// with 5 nodes) or a K<sub>3,3</sub> (complete bipartite graph on
|
|
539
|
+
/// 3 Red and 3 Blue nodes) subdivision.
|
|
540
|
+
///
|
|
541
|
+
/// The current implementation calculates either an embedding or a
|
|
542
|
+
/// Kuratowski subdivision. The running time of the algorithm is O(n).
|
|
543
|
+
///
|
|
544
|
+
/// \see PlanarDrawing, checkPlanarity()
|
|
545
|
+
template <typename Graph>
|
|
546
|
+
class PlanarEmbedding {
|
|
547
|
+
private:
|
|
548
|
+
|
|
549
|
+
TEMPLATE_GRAPH_TYPEDEFS(Graph);
|
|
550
|
+
|
|
551
|
+
const Graph& _graph;
|
|
552
|
+
typename Graph::template ArcMap<Arc> _embedding;
|
|
553
|
+
|
|
554
|
+
typename Graph::template EdgeMap<bool> _kuratowski;
|
|
555
|
+
|
|
556
|
+
private:
|
|
557
|
+
|
|
558
|
+
typedef typename Graph::template NodeMap<Arc> PredMap;
|
|
559
|
+
|
|
560
|
+
typedef typename Graph::template EdgeMap<bool> TreeMap;
|
|
561
|
+
|
|
562
|
+
typedef typename Graph::template NodeMap<int> OrderMap;
|
|
563
|
+
typedef std::vector<Node> OrderList;
|
|
564
|
+
|
|
565
|
+
typedef typename Graph::template NodeMap<int> LowMap;
|
|
566
|
+
typedef typename Graph::template NodeMap<int> AncestorMap;
|
|
567
|
+
|
|
568
|
+
typedef _planarity_bits::NodeDataNode<Graph> NodeDataNode;
|
|
569
|
+
typedef std::vector<NodeDataNode> NodeData;
|
|
570
|
+
|
|
571
|
+
typedef _planarity_bits::ChildListNode<Graph> ChildListNode;
|
|
572
|
+
typedef typename Graph::template NodeMap<ChildListNode> ChildLists;
|
|
573
|
+
|
|
574
|
+
typedef typename Graph::template NodeMap<std::list<int> > MergeRoots;
|
|
575
|
+
|
|
576
|
+
typedef typename Graph::template NodeMap<Arc> EmbedArc;
|
|
577
|
+
|
|
578
|
+
typedef _planarity_bits::ArcListNode<Graph> ArcListNode;
|
|
579
|
+
typedef typename Graph::template ArcMap<ArcListNode> ArcLists;
|
|
580
|
+
|
|
581
|
+
typedef typename Graph::template NodeMap<bool> FlipMap;
|
|
582
|
+
|
|
583
|
+
typedef typename Graph::template NodeMap<int> TypeMap;
|
|
584
|
+
|
|
585
|
+
enum IsolatorNodeType {
|
|
586
|
+
HIGHX = 6, LOWX = 7,
|
|
587
|
+
HIGHY = 8, LOWY = 9,
|
|
588
|
+
ROOT = 10, PERTINENT = 11,
|
|
589
|
+
INTERNAL = 12
|
|
590
|
+
};
|
|
591
|
+
|
|
592
|
+
public:
|
|
593
|
+
|
|
594
|
+
/// \brief The map type for storing the embedding
|
|
595
|
+
///
|
|
596
|
+
/// The map type for storing the embedding.
|
|
597
|
+
/// \see embeddingMap()
|
|
598
|
+
typedef typename Graph::template ArcMap<Arc> EmbeddingMap;
|
|
599
|
+
|
|
600
|
+
/// \brief Constructor
|
|
601
|
+
///
|
|
602
|
+
/// Constructor.
|
|
603
|
+
/// \pre The graph must be simple, i.e. it should not
|
|
604
|
+
/// contain parallel or loop arcs.
|
|
605
|
+
PlanarEmbedding(const Graph& graph)
|
|
606
|
+
: _graph(graph), _embedding(_graph), _kuratowski(graph, false) {}
|
|
607
|
+
|
|
608
|
+
/// \brief Run the algorithm.
|
|
609
|
+
///
|
|
610
|
+
/// This function runs the algorithm.
|
|
611
|
+
/// \param kuratowski If this parameter is set to \c false, then the
|
|
612
|
+
/// algorithm does not compute a Kuratowski subdivision.
|
|
613
|
+
/// \return \c true if the graph is planar.
|
|
614
|
+
bool run(bool kuratowski = true) {
|
|
615
|
+
typedef _planarity_bits::PlanarityVisitor<Graph> Visitor;
|
|
616
|
+
|
|
617
|
+
PredMap pred_map(_graph, INVALID);
|
|
618
|
+
TreeMap tree_map(_graph, false);
|
|
619
|
+
|
|
620
|
+
OrderMap order_map(_graph, -1);
|
|
621
|
+
OrderList order_list;
|
|
622
|
+
|
|
623
|
+
AncestorMap ancestor_map(_graph, -1);
|
|
624
|
+
LowMap low_map(_graph, -1);
|
|
625
|
+
|
|
626
|
+
Visitor visitor(_graph, pred_map, tree_map,
|
|
627
|
+
order_map, order_list, ancestor_map, low_map);
|
|
628
|
+
DfsVisit<Graph, Visitor> visit(_graph, visitor);
|
|
629
|
+
visit.run();
|
|
630
|
+
|
|
631
|
+
ChildLists child_lists(_graph);
|
|
632
|
+
createChildLists(tree_map, order_map, low_map, child_lists);
|
|
633
|
+
|
|
634
|
+
NodeData node_data(2 * order_list.size());
|
|
635
|
+
|
|
636
|
+
EmbedArc embed_arc(_graph, INVALID);
|
|
637
|
+
|
|
638
|
+
MergeRoots merge_roots(_graph);
|
|
639
|
+
|
|
640
|
+
ArcLists arc_lists(_graph);
|
|
641
|
+
|
|
642
|
+
FlipMap flip_map(_graph, false);
|
|
643
|
+
|
|
644
|
+
for (int i = order_list.size() - 1; i >= 0; --i) {
|
|
645
|
+
|
|
646
|
+
Node node = order_list[i];
|
|
647
|
+
|
|
648
|
+
node_data[i].first = INVALID;
|
|
649
|
+
|
|
650
|
+
Node source = node;
|
|
651
|
+
for (OutArcIt e(_graph, node); e != INVALID; ++e) {
|
|
652
|
+
Node target = _graph.target(e);
|
|
653
|
+
|
|
654
|
+
if (order_map[source] < order_map[target] && tree_map[e]) {
|
|
655
|
+
initFace(target, arc_lists, node_data,
|
|
656
|
+
pred_map, order_map, order_list);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
for (OutArcIt e(_graph, node); e != INVALID; ++e) {
|
|
661
|
+
Node target = _graph.target(e);
|
|
662
|
+
|
|
663
|
+
if (order_map[source] < order_map[target] && !tree_map[e]) {
|
|
664
|
+
embed_arc[target] = e;
|
|
665
|
+
walkUp(target, source, i, pred_map, low_map,
|
|
666
|
+
order_map, order_list, node_data, merge_roots);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
for (typename MergeRoots::Value::iterator it =
|
|
671
|
+
merge_roots[node].begin(); it != merge_roots[node].end(); ++it) {
|
|
672
|
+
int rn = *it;
|
|
673
|
+
walkDown(rn, i, node_data, arc_lists, flip_map, order_list,
|
|
674
|
+
child_lists, ancestor_map, low_map, embed_arc, merge_roots);
|
|
675
|
+
}
|
|
676
|
+
merge_roots[node].clear();
|
|
677
|
+
|
|
678
|
+
for (OutArcIt e(_graph, node); e != INVALID; ++e) {
|
|
679
|
+
Node target = _graph.target(e);
|
|
680
|
+
|
|
681
|
+
if (order_map[source] < order_map[target] && !tree_map[e]) {
|
|
682
|
+
if (embed_arc[target] != INVALID) {
|
|
683
|
+
if (kuratowski) {
|
|
684
|
+
isolateKuratowski(e, node_data, arc_lists, flip_map,
|
|
685
|
+
order_map, order_list, pred_map, child_lists,
|
|
686
|
+
ancestor_map, low_map,
|
|
687
|
+
embed_arc, merge_roots);
|
|
688
|
+
}
|
|
689
|
+
return false;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
for (int i = 0; i < int(order_list.size()); ++i) {
|
|
696
|
+
|
|
697
|
+
mergeRemainingFaces(order_list[i], node_data, order_list, order_map,
|
|
698
|
+
child_lists, arc_lists);
|
|
699
|
+
storeEmbedding(order_list[i], node_data, order_map, pred_map,
|
|
700
|
+
arc_lists, flip_map);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
return true;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
/// \brief Give back the successor of an arc
|
|
707
|
+
///
|
|
708
|
+
/// This function gives back the successor of an arc. It makes
|
|
709
|
+
/// possible to query the cyclic order of the outgoing arcs from
|
|
710
|
+
/// a node.
|
|
711
|
+
Arc next(const Arc& arc) const {
|
|
712
|
+
return _embedding[arc];
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
/// \brief Give back the calculated embedding map
|
|
716
|
+
///
|
|
717
|
+
/// This function gives back the calculated embedding map, which
|
|
718
|
+
/// contains the successor of each arc in the cyclic order of the
|
|
719
|
+
/// outgoing arcs of its source node.
|
|
720
|
+
const EmbeddingMap& embeddingMap() const {
|
|
721
|
+
return _embedding;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/// \brief Give back \c true if the given edge is in the Kuratowski
|
|
725
|
+
/// subdivision
|
|
726
|
+
///
|
|
727
|
+
/// This function gives back \c true if the given edge is in the found
|
|
728
|
+
/// Kuratowski subdivision.
|
|
729
|
+
/// \pre The \c run() function must be called with \c true parameter
|
|
730
|
+
/// before using this function.
|
|
731
|
+
bool kuratowski(const Edge& edge) const {
|
|
732
|
+
return _kuratowski[edge];
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
private:
|
|
736
|
+
|
|
737
|
+
void createChildLists(const TreeMap& tree_map, const OrderMap& order_map,
|
|
738
|
+
const LowMap& low_map, ChildLists& child_lists) {
|
|
739
|
+
|
|
740
|
+
for (NodeIt n(_graph); n != INVALID; ++n) {
|
|
741
|
+
Node source = n;
|
|
742
|
+
|
|
743
|
+
std::vector<Node> targets;
|
|
744
|
+
for (OutArcIt e(_graph, n); e != INVALID; ++e) {
|
|
745
|
+
Node target = _graph.target(e);
|
|
746
|
+
|
|
747
|
+
if (order_map[source] < order_map[target] && tree_map[e]) {
|
|
748
|
+
targets.push_back(target);
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
if (targets.size() == 0) {
|
|
753
|
+
child_lists[source].first = INVALID;
|
|
754
|
+
} else if (targets.size() == 1) {
|
|
755
|
+
child_lists[source].first = targets[0];
|
|
756
|
+
child_lists[targets[0]].prev = INVALID;
|
|
757
|
+
child_lists[targets[0]].next = INVALID;
|
|
758
|
+
} else {
|
|
759
|
+
radixSort(targets.begin(), targets.end(), mapToFunctor(low_map));
|
|
760
|
+
for (int i = 1; i < int(targets.size()); ++i) {
|
|
761
|
+
child_lists[targets[i]].prev = targets[i - 1];
|
|
762
|
+
child_lists[targets[i - 1]].next = targets[i];
|
|
763
|
+
}
|
|
764
|
+
child_lists[targets.back()].next = INVALID;
|
|
765
|
+
child_lists[targets.front()].prev = INVALID;
|
|
766
|
+
child_lists[source].first = targets.front();
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
void walkUp(const Node& node, Node root, int rorder,
|
|
772
|
+
const PredMap& pred_map, const LowMap& low_map,
|
|
773
|
+
const OrderMap& order_map, const OrderList& order_list,
|
|
774
|
+
NodeData& node_data, MergeRoots& merge_roots) {
|
|
775
|
+
|
|
776
|
+
int na, nb;
|
|
777
|
+
bool da, db;
|
|
778
|
+
|
|
779
|
+
na = nb = order_map[node];
|
|
780
|
+
da = true; db = false;
|
|
781
|
+
|
|
782
|
+
while (true) {
|
|
783
|
+
|
|
784
|
+
if (node_data[na].visited == rorder) break;
|
|
785
|
+
if (node_data[nb].visited == rorder) break;
|
|
786
|
+
|
|
787
|
+
node_data[na].visited = rorder;
|
|
788
|
+
node_data[nb].visited = rorder;
|
|
789
|
+
|
|
790
|
+
int rn = -1;
|
|
791
|
+
|
|
792
|
+
if (na >= int(order_list.size())) {
|
|
793
|
+
rn = na;
|
|
794
|
+
} else if (nb >= int(order_list.size())) {
|
|
795
|
+
rn = nb;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
if (rn == -1) {
|
|
799
|
+
int nn;
|
|
800
|
+
|
|
801
|
+
nn = da ? node_data[na].prev : node_data[na].next;
|
|
802
|
+
da = node_data[nn].prev != na;
|
|
803
|
+
na = nn;
|
|
804
|
+
|
|
805
|
+
nn = db ? node_data[nb].prev : node_data[nb].next;
|
|
806
|
+
db = node_data[nn].prev != nb;
|
|
807
|
+
nb = nn;
|
|
808
|
+
|
|
809
|
+
} else {
|
|
810
|
+
|
|
811
|
+
Node rep = order_list[rn - order_list.size()];
|
|
812
|
+
Node parent = _graph.source(pred_map[rep]);
|
|
813
|
+
|
|
814
|
+
if (low_map[rep] < rorder) {
|
|
815
|
+
merge_roots[parent].push_back(rn);
|
|
816
|
+
} else {
|
|
817
|
+
merge_roots[parent].push_front(rn);
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
if (parent != root) {
|
|
821
|
+
na = nb = order_map[parent];
|
|
822
|
+
da = true; db = false;
|
|
823
|
+
} else {
|
|
824
|
+
break;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
void walkDown(int rn, int rorder, NodeData& node_data,
|
|
831
|
+
ArcLists& arc_lists, FlipMap& flip_map,
|
|
832
|
+
OrderList& order_list, ChildLists& child_lists,
|
|
833
|
+
AncestorMap& ancestor_map, LowMap& low_map,
|
|
834
|
+
EmbedArc& embed_arc, MergeRoots& merge_roots) {
|
|
835
|
+
|
|
836
|
+
std::vector<std::pair<int, bool> > merge_stack;
|
|
837
|
+
|
|
838
|
+
for (int di = 0; di < 2; ++di) {
|
|
839
|
+
bool rd = di == 0;
|
|
840
|
+
int pn = rn;
|
|
841
|
+
int n = rd ? node_data[rn].next : node_data[rn].prev;
|
|
842
|
+
|
|
843
|
+
while (n != rn) {
|
|
844
|
+
|
|
845
|
+
Node node = order_list[n];
|
|
846
|
+
|
|
847
|
+
if (embed_arc[node] != INVALID) {
|
|
848
|
+
|
|
849
|
+
// Merging components on the critical path
|
|
850
|
+
while (!merge_stack.empty()) {
|
|
851
|
+
|
|
852
|
+
// Component root
|
|
853
|
+
int cn = merge_stack.back().first;
|
|
854
|
+
bool cd = merge_stack.back().second;
|
|
855
|
+
merge_stack.pop_back();
|
|
856
|
+
|
|
857
|
+
// Parent of component
|
|
858
|
+
int dn = merge_stack.back().first;
|
|
859
|
+
bool dd = merge_stack.back().second;
|
|
860
|
+
merge_stack.pop_back();
|
|
861
|
+
|
|
862
|
+
Node parent = order_list[dn];
|
|
863
|
+
|
|
864
|
+
// Erasing from merge_roots
|
|
865
|
+
merge_roots[parent].pop_front();
|
|
866
|
+
|
|
867
|
+
Node child = order_list[cn - order_list.size()];
|
|
868
|
+
|
|
869
|
+
// Erasing from child_lists
|
|
870
|
+
if (child_lists[child].prev != INVALID) {
|
|
871
|
+
child_lists[child_lists[child].prev].next =
|
|
872
|
+
child_lists[child].next;
|
|
873
|
+
} else {
|
|
874
|
+
child_lists[parent].first = child_lists[child].next;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
if (child_lists[child].next != INVALID) {
|
|
878
|
+
child_lists[child_lists[child].next].prev =
|
|
879
|
+
child_lists[child].prev;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
// Merging arcs + flipping
|
|
883
|
+
Arc de = node_data[dn].first;
|
|
884
|
+
Arc ce = node_data[cn].first;
|
|
885
|
+
|
|
886
|
+
flip_map[order_list[cn - order_list.size()]] = cd != dd;
|
|
887
|
+
if (cd != dd) {
|
|
888
|
+
std::swap(arc_lists[ce].prev, arc_lists[ce].next);
|
|
889
|
+
ce = arc_lists[ce].prev;
|
|
890
|
+
std::swap(arc_lists[ce].prev, arc_lists[ce].next);
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
{
|
|
894
|
+
Arc dne = arc_lists[de].next;
|
|
895
|
+
Arc cne = arc_lists[ce].next;
|
|
896
|
+
|
|
897
|
+
arc_lists[de].next = cne;
|
|
898
|
+
arc_lists[ce].next = dne;
|
|
899
|
+
|
|
900
|
+
arc_lists[dne].prev = ce;
|
|
901
|
+
arc_lists[cne].prev = de;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
if (dd) {
|
|
905
|
+
node_data[dn].first = ce;
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
// Merging external faces
|
|
909
|
+
{
|
|
910
|
+
int en = cn;
|
|
911
|
+
cn = cd ? node_data[cn].prev : node_data[cn].next;
|
|
912
|
+
cd = node_data[cn].next == en;
|
|
913
|
+
|
|
914
|
+
if (node_data[cn].prev == node_data[cn].next &&
|
|
915
|
+
node_data[cn].inverted) {
|
|
916
|
+
cd = !cd;
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
if (cd) node_data[cn].next = dn; else node_data[cn].prev = dn;
|
|
921
|
+
if (dd) node_data[dn].prev = cn; else node_data[dn].next = cn;
|
|
922
|
+
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
bool d = pn == node_data[n].prev;
|
|
926
|
+
|
|
927
|
+
if (node_data[n].prev == node_data[n].next &&
|
|
928
|
+
node_data[n].inverted) {
|
|
929
|
+
d = !d;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
// Add new arc
|
|
933
|
+
{
|
|
934
|
+
Arc arc = embed_arc[node];
|
|
935
|
+
Arc re = node_data[rn].first;
|
|
936
|
+
|
|
937
|
+
arc_lists[arc_lists[re].next].prev = arc;
|
|
938
|
+
arc_lists[arc].next = arc_lists[re].next;
|
|
939
|
+
arc_lists[arc].prev = re;
|
|
940
|
+
arc_lists[re].next = arc;
|
|
941
|
+
|
|
942
|
+
if (!rd) {
|
|
943
|
+
node_data[rn].first = arc;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
Arc rev = _graph.oppositeArc(arc);
|
|
947
|
+
Arc e = node_data[n].first;
|
|
948
|
+
|
|
949
|
+
arc_lists[arc_lists[e].next].prev = rev;
|
|
950
|
+
arc_lists[rev].next = arc_lists[e].next;
|
|
951
|
+
arc_lists[rev].prev = e;
|
|
952
|
+
arc_lists[e].next = rev;
|
|
953
|
+
|
|
954
|
+
if (d) {
|
|
955
|
+
node_data[n].first = rev;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
// Embedding arc into external face
|
|
961
|
+
if (rd) node_data[rn].next = n; else node_data[rn].prev = n;
|
|
962
|
+
if (d) node_data[n].prev = rn; else node_data[n].next = rn;
|
|
963
|
+
pn = rn;
|
|
964
|
+
|
|
965
|
+
embed_arc[order_list[n]] = INVALID;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
if (!merge_roots[node].empty()) {
|
|
969
|
+
|
|
970
|
+
bool d = pn == node_data[n].prev;
|
|
971
|
+
if (node_data[n].prev == node_data[n].next &&
|
|
972
|
+
node_data[n].inverted) {
|
|
973
|
+
d = !d;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
merge_stack.push_back(std::make_pair(n, d));
|
|
977
|
+
|
|
978
|
+
int rn = merge_roots[node].front();
|
|
979
|
+
|
|
980
|
+
int xn = node_data[rn].next;
|
|
981
|
+
Node xnode = order_list[xn];
|
|
982
|
+
|
|
983
|
+
int yn = node_data[rn].prev;
|
|
984
|
+
Node ynode = order_list[yn];
|
|
985
|
+
|
|
986
|
+
bool rd;
|
|
987
|
+
if (!external(xnode, rorder, child_lists, ancestor_map, low_map)) {
|
|
988
|
+
rd = true;
|
|
989
|
+
} else if (!external(ynode, rorder, child_lists,
|
|
990
|
+
ancestor_map, low_map)) {
|
|
991
|
+
rd = false;
|
|
992
|
+
} else if (pertinent(xnode, embed_arc, merge_roots)) {
|
|
993
|
+
rd = true;
|
|
994
|
+
} else {
|
|
995
|
+
rd = false;
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
merge_stack.push_back(std::make_pair(rn, rd));
|
|
999
|
+
|
|
1000
|
+
pn = rn;
|
|
1001
|
+
n = rd ? xn : yn;
|
|
1002
|
+
|
|
1003
|
+
} else if (!external(node, rorder, child_lists,
|
|
1004
|
+
ancestor_map, low_map)) {
|
|
1005
|
+
int nn = (node_data[n].next != pn ?
|
|
1006
|
+
node_data[n].next : node_data[n].prev);
|
|
1007
|
+
|
|
1008
|
+
bool nd = n == node_data[nn].prev;
|
|
1009
|
+
|
|
1010
|
+
if (nd) node_data[nn].prev = pn;
|
|
1011
|
+
else node_data[nn].next = pn;
|
|
1012
|
+
|
|
1013
|
+
if (n == node_data[pn].prev) node_data[pn].prev = nn;
|
|
1014
|
+
else node_data[pn].next = nn;
|
|
1015
|
+
|
|
1016
|
+
node_data[nn].inverted =
|
|
1017
|
+
(node_data[nn].prev == node_data[nn].next && nd != rd);
|
|
1018
|
+
|
|
1019
|
+
n = nn;
|
|
1020
|
+
}
|
|
1021
|
+
else break;
|
|
1022
|
+
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
if (!merge_stack.empty() || n == rn) {
|
|
1026
|
+
break;
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
void initFace(const Node& node, ArcLists& arc_lists,
|
|
1032
|
+
NodeData& node_data, const PredMap& pred_map,
|
|
1033
|
+
const OrderMap& order_map, const OrderList& order_list) {
|
|
1034
|
+
int n = order_map[node];
|
|
1035
|
+
int rn = n + order_list.size();
|
|
1036
|
+
|
|
1037
|
+
node_data[n].next = node_data[n].prev = rn;
|
|
1038
|
+
node_data[rn].next = node_data[rn].prev = n;
|
|
1039
|
+
|
|
1040
|
+
node_data[n].visited = order_list.size();
|
|
1041
|
+
node_data[rn].visited = order_list.size();
|
|
1042
|
+
|
|
1043
|
+
node_data[n].inverted = false;
|
|
1044
|
+
node_data[rn].inverted = false;
|
|
1045
|
+
|
|
1046
|
+
Arc arc = pred_map[node];
|
|
1047
|
+
Arc rev = _graph.oppositeArc(arc);
|
|
1048
|
+
|
|
1049
|
+
node_data[rn].first = arc;
|
|
1050
|
+
node_data[n].first = rev;
|
|
1051
|
+
|
|
1052
|
+
arc_lists[arc].prev = arc;
|
|
1053
|
+
arc_lists[arc].next = arc;
|
|
1054
|
+
|
|
1055
|
+
arc_lists[rev].prev = rev;
|
|
1056
|
+
arc_lists[rev].next = rev;
|
|
1057
|
+
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
void mergeRemainingFaces(const Node& node, NodeData& node_data,
|
|
1061
|
+
OrderList& order_list, OrderMap& order_map,
|
|
1062
|
+
ChildLists& child_lists, ArcLists& arc_lists) {
|
|
1063
|
+
while (child_lists[node].first != INVALID) {
|
|
1064
|
+
int dd = order_map[node];
|
|
1065
|
+
Node child = child_lists[node].first;
|
|
1066
|
+
int cd = order_map[child] + order_list.size();
|
|
1067
|
+
child_lists[node].first = child_lists[child].next;
|
|
1068
|
+
|
|
1069
|
+
Arc de = node_data[dd].first;
|
|
1070
|
+
Arc ce = node_data[cd].first;
|
|
1071
|
+
|
|
1072
|
+
if (de != INVALID) {
|
|
1073
|
+
Arc dne = arc_lists[de].next;
|
|
1074
|
+
Arc cne = arc_lists[ce].next;
|
|
1075
|
+
|
|
1076
|
+
arc_lists[de].next = cne;
|
|
1077
|
+
arc_lists[ce].next = dne;
|
|
1078
|
+
|
|
1079
|
+
arc_lists[dne].prev = ce;
|
|
1080
|
+
arc_lists[cne].prev = de;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
node_data[dd].first = ce;
|
|
1084
|
+
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
void storeEmbedding(const Node& node, NodeData& node_data,
|
|
1089
|
+
OrderMap& order_map, PredMap& pred_map,
|
|
1090
|
+
ArcLists& arc_lists, FlipMap& flip_map) {
|
|
1091
|
+
|
|
1092
|
+
if (node_data[order_map[node]].first == INVALID) return;
|
|
1093
|
+
|
|
1094
|
+
if (pred_map[node] != INVALID) {
|
|
1095
|
+
Node source = _graph.source(pred_map[node]);
|
|
1096
|
+
flip_map[node] = flip_map[node] != flip_map[source];
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
Arc first = node_data[order_map[node]].first;
|
|
1100
|
+
Arc prev = first;
|
|
1101
|
+
|
|
1102
|
+
Arc arc = flip_map[node] ?
|
|
1103
|
+
arc_lists[prev].prev : arc_lists[prev].next;
|
|
1104
|
+
|
|
1105
|
+
_embedding[prev] = arc;
|
|
1106
|
+
|
|
1107
|
+
while (arc != first) {
|
|
1108
|
+
Arc next = arc_lists[arc].prev == prev ?
|
|
1109
|
+
arc_lists[arc].next : arc_lists[arc].prev;
|
|
1110
|
+
prev = arc; arc = next;
|
|
1111
|
+
_embedding[prev] = arc;
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
|
|
1116
|
+
bool external(const Node& node, int rorder,
|
|
1117
|
+
ChildLists& child_lists, AncestorMap& ancestor_map,
|
|
1118
|
+
LowMap& low_map) {
|
|
1119
|
+
Node child = child_lists[node].first;
|
|
1120
|
+
|
|
1121
|
+
if (child != INVALID) {
|
|
1122
|
+
if (low_map[child] < rorder) return true;
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
if (ancestor_map[node] < rorder) return true;
|
|
1126
|
+
|
|
1127
|
+
return false;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
bool pertinent(const Node& node, const EmbedArc& embed_arc,
|
|
1131
|
+
const MergeRoots& merge_roots) {
|
|
1132
|
+
return !merge_roots[node].empty() || embed_arc[node] != INVALID;
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
int lowPoint(const Node& node, OrderMap& order_map, ChildLists& child_lists,
|
|
1136
|
+
AncestorMap& ancestor_map, LowMap& low_map) {
|
|
1137
|
+
int low_point;
|
|
1138
|
+
|
|
1139
|
+
Node child = child_lists[node].first;
|
|
1140
|
+
|
|
1141
|
+
if (child != INVALID) {
|
|
1142
|
+
low_point = low_map[child];
|
|
1143
|
+
} else {
|
|
1144
|
+
low_point = order_map[node];
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
if (low_point > ancestor_map[node]) {
|
|
1148
|
+
low_point = ancestor_map[node];
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
return low_point;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
int findComponentRoot(Node root, Node node, ChildLists& child_lists,
|
|
1155
|
+
OrderMap& order_map, OrderList& order_list) {
|
|
1156
|
+
|
|
1157
|
+
int order = order_map[root];
|
|
1158
|
+
int norder = order_map[node];
|
|
1159
|
+
|
|
1160
|
+
Node child = child_lists[root].first;
|
|
1161
|
+
while (child != INVALID) {
|
|
1162
|
+
int corder = order_map[child];
|
|
1163
|
+
if (corder > order && corder < norder) {
|
|
1164
|
+
order = corder;
|
|
1165
|
+
}
|
|
1166
|
+
child = child_lists[child].next;
|
|
1167
|
+
}
|
|
1168
|
+
return order + order_list.size();
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
Node findPertinent(Node node, OrderMap& order_map, NodeData& node_data,
|
|
1172
|
+
EmbedArc& embed_arc, MergeRoots& merge_roots) {
|
|
1173
|
+
Node wnode =_graph.target(node_data[order_map[node]].first);
|
|
1174
|
+
while (!pertinent(wnode, embed_arc, merge_roots)) {
|
|
1175
|
+
wnode = _graph.target(node_data[order_map[wnode]].first);
|
|
1176
|
+
}
|
|
1177
|
+
return wnode;
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
|
|
1181
|
+
Node findExternal(Node node, int rorder, OrderMap& order_map,
|
|
1182
|
+
ChildLists& child_lists, AncestorMap& ancestor_map,
|
|
1183
|
+
LowMap& low_map, NodeData& node_data) {
|
|
1184
|
+
Node wnode =_graph.target(node_data[order_map[node]].first);
|
|
1185
|
+
while (!external(wnode, rorder, child_lists, ancestor_map, low_map)) {
|
|
1186
|
+
wnode = _graph.target(node_data[order_map[wnode]].first);
|
|
1187
|
+
}
|
|
1188
|
+
return wnode;
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
void markCommonPath(Node node, int rorder, Node& wnode, Node& znode,
|
|
1192
|
+
OrderList& order_list, OrderMap& order_map,
|
|
1193
|
+
NodeData& node_data, ArcLists& arc_lists,
|
|
1194
|
+
EmbedArc& embed_arc, MergeRoots& merge_roots,
|
|
1195
|
+
ChildLists& child_lists, AncestorMap& ancestor_map,
|
|
1196
|
+
LowMap& low_map) {
|
|
1197
|
+
|
|
1198
|
+
Node cnode = node;
|
|
1199
|
+
Node pred = INVALID;
|
|
1200
|
+
|
|
1201
|
+
while (true) {
|
|
1202
|
+
|
|
1203
|
+
bool pert = pertinent(cnode, embed_arc, merge_roots);
|
|
1204
|
+
bool ext = external(cnode, rorder, child_lists, ancestor_map, low_map);
|
|
1205
|
+
|
|
1206
|
+
if (pert && ext) {
|
|
1207
|
+
if (!merge_roots[cnode].empty()) {
|
|
1208
|
+
int cn = merge_roots[cnode].back();
|
|
1209
|
+
|
|
1210
|
+
if (low_map[order_list[cn - order_list.size()]] < rorder) {
|
|
1211
|
+
Arc arc = node_data[cn].first;
|
|
1212
|
+
_kuratowski.set(arc, true);
|
|
1213
|
+
|
|
1214
|
+
pred = cnode;
|
|
1215
|
+
cnode = _graph.target(arc);
|
|
1216
|
+
|
|
1217
|
+
continue;
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
wnode = znode = cnode;
|
|
1221
|
+
return;
|
|
1222
|
+
|
|
1223
|
+
} else if (pert) {
|
|
1224
|
+
wnode = cnode;
|
|
1225
|
+
|
|
1226
|
+
while (!external(cnode, rorder, child_lists, ancestor_map, low_map)) {
|
|
1227
|
+
Arc arc = node_data[order_map[cnode]].first;
|
|
1228
|
+
|
|
1229
|
+
if (_graph.target(arc) == pred) {
|
|
1230
|
+
arc = arc_lists[arc].next;
|
|
1231
|
+
}
|
|
1232
|
+
_kuratowski.set(arc, true);
|
|
1233
|
+
|
|
1234
|
+
Node next = _graph.target(arc);
|
|
1235
|
+
pred = cnode; cnode = next;
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
znode = cnode;
|
|
1239
|
+
return;
|
|
1240
|
+
|
|
1241
|
+
} else if (ext) {
|
|
1242
|
+
znode = cnode;
|
|
1243
|
+
|
|
1244
|
+
while (!pertinent(cnode, embed_arc, merge_roots)) {
|
|
1245
|
+
Arc arc = node_data[order_map[cnode]].first;
|
|
1246
|
+
|
|
1247
|
+
if (_graph.target(arc) == pred) {
|
|
1248
|
+
arc = arc_lists[arc].next;
|
|
1249
|
+
}
|
|
1250
|
+
_kuratowski.set(arc, true);
|
|
1251
|
+
|
|
1252
|
+
Node next = _graph.target(arc);
|
|
1253
|
+
pred = cnode; cnode = next;
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
wnode = cnode;
|
|
1257
|
+
return;
|
|
1258
|
+
|
|
1259
|
+
} else {
|
|
1260
|
+
Arc arc = node_data[order_map[cnode]].first;
|
|
1261
|
+
|
|
1262
|
+
if (_graph.target(arc) == pred) {
|
|
1263
|
+
arc = arc_lists[arc].next;
|
|
1264
|
+
}
|
|
1265
|
+
_kuratowski.set(arc, true);
|
|
1266
|
+
|
|
1267
|
+
Node next = _graph.target(arc);
|
|
1268
|
+
pred = cnode; cnode = next;
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
void orientComponent(Node root, int rn, OrderMap& order_map,
|
|
1276
|
+
PredMap& pred_map, NodeData& node_data,
|
|
1277
|
+
ArcLists& arc_lists, FlipMap& flip_map,
|
|
1278
|
+
TypeMap& type_map) {
|
|
1279
|
+
node_data[order_map[root]].first = node_data[rn].first;
|
|
1280
|
+
type_map[root] = 1;
|
|
1281
|
+
|
|
1282
|
+
std::vector<Node> st, qu;
|
|
1283
|
+
|
|
1284
|
+
st.push_back(root);
|
|
1285
|
+
while (!st.empty()) {
|
|
1286
|
+
Node node = st.back();
|
|
1287
|
+
st.pop_back();
|
|
1288
|
+
qu.push_back(node);
|
|
1289
|
+
|
|
1290
|
+
Arc arc = node_data[order_map[node]].first;
|
|
1291
|
+
|
|
1292
|
+
if (type_map[_graph.target(arc)] == 0) {
|
|
1293
|
+
st.push_back(_graph.target(arc));
|
|
1294
|
+
type_map[_graph.target(arc)] = 1;
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
Arc last = arc, pred = arc;
|
|
1298
|
+
arc = arc_lists[arc].next;
|
|
1299
|
+
while (arc != last) {
|
|
1300
|
+
|
|
1301
|
+
if (type_map[_graph.target(arc)] == 0) {
|
|
1302
|
+
st.push_back(_graph.target(arc));
|
|
1303
|
+
type_map[_graph.target(arc)] = 1;
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
Arc next = arc_lists[arc].next != pred ?
|
|
1307
|
+
arc_lists[arc].next : arc_lists[arc].prev;
|
|
1308
|
+
pred = arc; arc = next;
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
type_map[root] = 2;
|
|
1314
|
+
flip_map[root] = false;
|
|
1315
|
+
|
|
1316
|
+
for (int i = 1; i < int(qu.size()); ++i) {
|
|
1317
|
+
|
|
1318
|
+
Node node = qu[i];
|
|
1319
|
+
|
|
1320
|
+
while (type_map[node] != 2) {
|
|
1321
|
+
st.push_back(node);
|
|
1322
|
+
type_map[node] = 2;
|
|
1323
|
+
node = _graph.source(pred_map[node]);
|
|
1324
|
+
}
|
|
1325
|
+
|
|
1326
|
+
bool flip = flip_map[node];
|
|
1327
|
+
|
|
1328
|
+
while (!st.empty()) {
|
|
1329
|
+
node = st.back();
|
|
1330
|
+
st.pop_back();
|
|
1331
|
+
|
|
1332
|
+
flip_map[node] = flip != flip_map[node];
|
|
1333
|
+
flip = flip_map[node];
|
|
1334
|
+
|
|
1335
|
+
if (flip) {
|
|
1336
|
+
Arc arc = node_data[order_map[node]].first;
|
|
1337
|
+
std::swap(arc_lists[arc].prev, arc_lists[arc].next);
|
|
1338
|
+
arc = arc_lists[arc].prev;
|
|
1339
|
+
std::swap(arc_lists[arc].prev, arc_lists[arc].next);
|
|
1340
|
+
node_data[order_map[node]].first = arc;
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
for (int i = 0; i < int(qu.size()); ++i) {
|
|
1346
|
+
|
|
1347
|
+
Arc arc = node_data[order_map[qu[i]]].first;
|
|
1348
|
+
Arc last = arc, pred = arc;
|
|
1349
|
+
|
|
1350
|
+
arc = arc_lists[arc].next;
|
|
1351
|
+
while (arc != last) {
|
|
1352
|
+
|
|
1353
|
+
if (arc_lists[arc].next == pred) {
|
|
1354
|
+
std::swap(arc_lists[arc].next, arc_lists[arc].prev);
|
|
1355
|
+
}
|
|
1356
|
+
pred = arc; arc = arc_lists[arc].next;
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
void setFaceFlags(Node root, Node wnode, Node ynode, Node xnode,
|
|
1363
|
+
OrderMap& order_map, NodeData& node_data,
|
|
1364
|
+
TypeMap& type_map) {
|
|
1365
|
+
Node node = _graph.target(node_data[order_map[root]].first);
|
|
1366
|
+
|
|
1367
|
+
while (node != ynode) {
|
|
1368
|
+
type_map[node] = HIGHY;
|
|
1369
|
+
node = _graph.target(node_data[order_map[node]].first);
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
while (node != wnode) {
|
|
1373
|
+
type_map[node] = LOWY;
|
|
1374
|
+
node = _graph.target(node_data[order_map[node]].first);
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
node = _graph.target(node_data[order_map[wnode]].first);
|
|
1378
|
+
|
|
1379
|
+
while (node != xnode) {
|
|
1380
|
+
type_map[node] = LOWX;
|
|
1381
|
+
node = _graph.target(node_data[order_map[node]].first);
|
|
1382
|
+
}
|
|
1383
|
+
type_map[node] = LOWX;
|
|
1384
|
+
|
|
1385
|
+
node = _graph.target(node_data[order_map[xnode]].first);
|
|
1386
|
+
while (node != root) {
|
|
1387
|
+
type_map[node] = HIGHX;
|
|
1388
|
+
node = _graph.target(node_data[order_map[node]].first);
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
type_map[wnode] = PERTINENT;
|
|
1392
|
+
type_map[root] = ROOT;
|
|
1393
|
+
}
|
|
1394
|
+
|
|
1395
|
+
void findInternalPath(std::vector<Arc>& ipath,
|
|
1396
|
+
Node wnode, Node root, TypeMap& type_map,
|
|
1397
|
+
OrderMap& order_map, NodeData& node_data,
|
|
1398
|
+
ArcLists& arc_lists) {
|
|
1399
|
+
std::vector<Arc> st;
|
|
1400
|
+
|
|
1401
|
+
Node node = wnode;
|
|
1402
|
+
|
|
1403
|
+
while (node != root) {
|
|
1404
|
+
Arc arc = arc_lists[node_data[order_map[node]].first].next;
|
|
1405
|
+
st.push_back(arc);
|
|
1406
|
+
node = _graph.target(arc);
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
while (true) {
|
|
1410
|
+
Arc arc = st.back();
|
|
1411
|
+
if (type_map[_graph.target(arc)] == LOWX ||
|
|
1412
|
+
type_map[_graph.target(arc)] == HIGHX) {
|
|
1413
|
+
break;
|
|
1414
|
+
}
|
|
1415
|
+
if (type_map[_graph.target(arc)] == 2) {
|
|
1416
|
+
type_map[_graph.target(arc)] = 3;
|
|
1417
|
+
|
|
1418
|
+
arc = arc_lists[_graph.oppositeArc(arc)].next;
|
|
1419
|
+
st.push_back(arc);
|
|
1420
|
+
} else {
|
|
1421
|
+
st.pop_back();
|
|
1422
|
+
arc = arc_lists[arc].next;
|
|
1423
|
+
|
|
1424
|
+
while (_graph.oppositeArc(arc) == st.back()) {
|
|
1425
|
+
arc = st.back();
|
|
1426
|
+
st.pop_back();
|
|
1427
|
+
arc = arc_lists[arc].next;
|
|
1428
|
+
}
|
|
1429
|
+
st.push_back(arc);
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
for (int i = 0; i < int(st.size()); ++i) {
|
|
1434
|
+
if (type_map[_graph.target(st[i])] != LOWY &&
|
|
1435
|
+
type_map[_graph.target(st[i])] != HIGHY) {
|
|
1436
|
+
for (; i < int(st.size()); ++i) {
|
|
1437
|
+
ipath.push_back(st[i]);
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
void setInternalFlags(std::vector<Arc>& ipath, TypeMap& type_map) {
|
|
1444
|
+
for (int i = 1; i < int(ipath.size()); ++i) {
|
|
1445
|
+
type_map[_graph.source(ipath[i])] = INTERNAL;
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
void findPilePath(std::vector<Arc>& ppath,
|
|
1450
|
+
Node root, TypeMap& type_map, OrderMap& order_map,
|
|
1451
|
+
NodeData& node_data, ArcLists& arc_lists) {
|
|
1452
|
+
std::vector<Arc> st;
|
|
1453
|
+
|
|
1454
|
+
st.push_back(_graph.oppositeArc(node_data[order_map[root]].first));
|
|
1455
|
+
st.push_back(node_data[order_map[root]].first);
|
|
1456
|
+
|
|
1457
|
+
while (st.size() > 1) {
|
|
1458
|
+
Arc arc = st.back();
|
|
1459
|
+
if (type_map[_graph.target(arc)] == INTERNAL) {
|
|
1460
|
+
break;
|
|
1461
|
+
}
|
|
1462
|
+
if (type_map[_graph.target(arc)] == 3) {
|
|
1463
|
+
type_map[_graph.target(arc)] = 4;
|
|
1464
|
+
|
|
1465
|
+
arc = arc_lists[_graph.oppositeArc(arc)].next;
|
|
1466
|
+
st.push_back(arc);
|
|
1467
|
+
} else {
|
|
1468
|
+
st.pop_back();
|
|
1469
|
+
arc = arc_lists[arc].next;
|
|
1470
|
+
|
|
1471
|
+
while (!st.empty() && _graph.oppositeArc(arc) == st.back()) {
|
|
1472
|
+
arc = st.back();
|
|
1473
|
+
st.pop_back();
|
|
1474
|
+
arc = arc_lists[arc].next;
|
|
1475
|
+
}
|
|
1476
|
+
st.push_back(arc);
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
for (int i = 1; i < int(st.size()); ++i) {
|
|
1481
|
+
ppath.push_back(st[i]);
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
|
|
1486
|
+
int markExternalPath(Node node, OrderMap& order_map,
|
|
1487
|
+
ChildLists& child_lists, PredMap& pred_map,
|
|
1488
|
+
AncestorMap& ancestor_map, LowMap& low_map) {
|
|
1489
|
+
int lp = lowPoint(node, order_map, child_lists,
|
|
1490
|
+
ancestor_map, low_map);
|
|
1491
|
+
|
|
1492
|
+
if (ancestor_map[node] != lp) {
|
|
1493
|
+
node = child_lists[node].first;
|
|
1494
|
+
_kuratowski[pred_map[node]] = true;
|
|
1495
|
+
|
|
1496
|
+
while (ancestor_map[node] != lp) {
|
|
1497
|
+
for (OutArcIt e(_graph, node); e != INVALID; ++e) {
|
|
1498
|
+
Node tnode = _graph.target(e);
|
|
1499
|
+
if (order_map[tnode] > order_map[node] && low_map[tnode] == lp) {
|
|
1500
|
+
node = tnode;
|
|
1501
|
+
_kuratowski[e] = true;
|
|
1502
|
+
break;
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
for (OutArcIt e(_graph, node); e != INVALID; ++e) {
|
|
1509
|
+
if (order_map[_graph.target(e)] == lp) {
|
|
1510
|
+
_kuratowski[e] = true;
|
|
1511
|
+
break;
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
return lp;
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
void markPertinentPath(Node node, OrderMap& order_map,
|
|
1519
|
+
NodeData& node_data, ArcLists& arc_lists,
|
|
1520
|
+
EmbedArc& embed_arc, MergeRoots& merge_roots) {
|
|
1521
|
+
while (embed_arc[node] == INVALID) {
|
|
1522
|
+
int n = merge_roots[node].front();
|
|
1523
|
+
Arc arc = node_data[n].first;
|
|
1524
|
+
|
|
1525
|
+
_kuratowski.set(arc, true);
|
|
1526
|
+
|
|
1527
|
+
Node pred = node;
|
|
1528
|
+
node = _graph.target(arc);
|
|
1529
|
+
while (!pertinent(node, embed_arc, merge_roots)) {
|
|
1530
|
+
arc = node_data[order_map[node]].first;
|
|
1531
|
+
if (_graph.target(arc) == pred) {
|
|
1532
|
+
arc = arc_lists[arc].next;
|
|
1533
|
+
}
|
|
1534
|
+
_kuratowski.set(arc, true);
|
|
1535
|
+
pred = node;
|
|
1536
|
+
node = _graph.target(arc);
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
_kuratowski.set(embed_arc[node], true);
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
void markPredPath(Node node, Node snode, PredMap& pred_map) {
|
|
1543
|
+
while (node != snode) {
|
|
1544
|
+
_kuratowski.set(pred_map[node], true);
|
|
1545
|
+
node = _graph.source(pred_map[node]);
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
void markFacePath(Node ynode, Node xnode,
|
|
1550
|
+
OrderMap& order_map, NodeData& node_data) {
|
|
1551
|
+
Arc arc = node_data[order_map[ynode]].first;
|
|
1552
|
+
Node node = _graph.target(arc);
|
|
1553
|
+
_kuratowski.set(arc, true);
|
|
1554
|
+
|
|
1555
|
+
while (node != xnode) {
|
|
1556
|
+
arc = node_data[order_map[node]].first;
|
|
1557
|
+
_kuratowski.set(arc, true);
|
|
1558
|
+
node = _graph.target(arc);
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
void markInternalPath(std::vector<Arc>& path) {
|
|
1563
|
+
for (int i = 0; i < int(path.size()); ++i) {
|
|
1564
|
+
_kuratowski.set(path[i], true);
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
void markPilePath(std::vector<Arc>& path) {
|
|
1569
|
+
for (int i = 0; i < int(path.size()); ++i) {
|
|
1570
|
+
_kuratowski.set(path[i], true);
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
void isolateKuratowski(Arc arc, NodeData& node_data,
|
|
1575
|
+
ArcLists& arc_lists, FlipMap& flip_map,
|
|
1576
|
+
OrderMap& order_map, OrderList& order_list,
|
|
1577
|
+
PredMap& pred_map, ChildLists& child_lists,
|
|
1578
|
+
AncestorMap& ancestor_map, LowMap& low_map,
|
|
1579
|
+
EmbedArc& embed_arc, MergeRoots& merge_roots) {
|
|
1580
|
+
|
|
1581
|
+
Node root = _graph.source(arc);
|
|
1582
|
+
Node enode = _graph.target(arc);
|
|
1583
|
+
|
|
1584
|
+
int rorder = order_map[root];
|
|
1585
|
+
|
|
1586
|
+
TypeMap type_map(_graph, 0);
|
|
1587
|
+
|
|
1588
|
+
int rn = findComponentRoot(root, enode, child_lists,
|
|
1589
|
+
order_map, order_list);
|
|
1590
|
+
|
|
1591
|
+
Node xnode = order_list[node_data[rn].next];
|
|
1592
|
+
Node ynode = order_list[node_data[rn].prev];
|
|
1593
|
+
|
|
1594
|
+
// Minor-A
|
|
1595
|
+
{
|
|
1596
|
+
while (!merge_roots[xnode].empty() || !merge_roots[ynode].empty()) {
|
|
1597
|
+
|
|
1598
|
+
if (!merge_roots[xnode].empty()) {
|
|
1599
|
+
root = xnode;
|
|
1600
|
+
rn = merge_roots[xnode].front();
|
|
1601
|
+
} else {
|
|
1602
|
+
root = ynode;
|
|
1603
|
+
rn = merge_roots[ynode].front();
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
xnode = order_list[node_data[rn].next];
|
|
1607
|
+
ynode = order_list[node_data[rn].prev];
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
if (root != _graph.source(arc)) {
|
|
1611
|
+
orientComponent(root, rn, order_map, pred_map,
|
|
1612
|
+
node_data, arc_lists, flip_map, type_map);
|
|
1613
|
+
markFacePath(root, root, order_map, node_data);
|
|
1614
|
+
int xlp = markExternalPath(xnode, order_map, child_lists,
|
|
1615
|
+
pred_map, ancestor_map, low_map);
|
|
1616
|
+
int ylp = markExternalPath(ynode, order_map, child_lists,
|
|
1617
|
+
pred_map, ancestor_map, low_map);
|
|
1618
|
+
markPredPath(root, order_list[xlp < ylp ? xlp : ylp], pred_map);
|
|
1619
|
+
Node lwnode = findPertinent(ynode, order_map, node_data,
|
|
1620
|
+
embed_arc, merge_roots);
|
|
1621
|
+
|
|
1622
|
+
markPertinentPath(lwnode, order_map, node_data, arc_lists,
|
|
1623
|
+
embed_arc, merge_roots);
|
|
1624
|
+
|
|
1625
|
+
return;
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
orientComponent(root, rn, order_map, pred_map,
|
|
1630
|
+
node_data, arc_lists, flip_map, type_map);
|
|
1631
|
+
|
|
1632
|
+
Node wnode = findPertinent(ynode, order_map, node_data,
|
|
1633
|
+
embed_arc, merge_roots);
|
|
1634
|
+
setFaceFlags(root, wnode, ynode, xnode, order_map, node_data, type_map);
|
|
1635
|
+
|
|
1636
|
+
|
|
1637
|
+
//Minor-B
|
|
1638
|
+
if (!merge_roots[wnode].empty()) {
|
|
1639
|
+
int cn = merge_roots[wnode].back();
|
|
1640
|
+
Node rep = order_list[cn - order_list.size()];
|
|
1641
|
+
if (low_map[rep] < rorder) {
|
|
1642
|
+
markFacePath(root, root, order_map, node_data);
|
|
1643
|
+
int xlp = markExternalPath(xnode, order_map, child_lists,
|
|
1644
|
+
pred_map, ancestor_map, low_map);
|
|
1645
|
+
int ylp = markExternalPath(ynode, order_map, child_lists,
|
|
1646
|
+
pred_map, ancestor_map, low_map);
|
|
1647
|
+
|
|
1648
|
+
Node lwnode, lznode;
|
|
1649
|
+
markCommonPath(wnode, rorder, lwnode, lznode, order_list,
|
|
1650
|
+
order_map, node_data, arc_lists, embed_arc,
|
|
1651
|
+
merge_roots, child_lists, ancestor_map, low_map);
|
|
1652
|
+
|
|
1653
|
+
markPertinentPath(lwnode, order_map, node_data, arc_lists,
|
|
1654
|
+
embed_arc, merge_roots);
|
|
1655
|
+
int zlp = markExternalPath(lznode, order_map, child_lists,
|
|
1656
|
+
pred_map, ancestor_map, low_map);
|
|
1657
|
+
|
|
1658
|
+
int minlp = xlp < ylp ? xlp : ylp;
|
|
1659
|
+
if (zlp < minlp) minlp = zlp;
|
|
1660
|
+
|
|
1661
|
+
int maxlp = xlp > ylp ? xlp : ylp;
|
|
1662
|
+
if (zlp > maxlp) maxlp = zlp;
|
|
1663
|
+
|
|
1664
|
+
markPredPath(order_list[maxlp], order_list[minlp], pred_map);
|
|
1665
|
+
|
|
1666
|
+
return;
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
Node pxnode, pynode;
|
|
1671
|
+
std::vector<Arc> ipath;
|
|
1672
|
+
findInternalPath(ipath, wnode, root, type_map, order_map,
|
|
1673
|
+
node_data, arc_lists);
|
|
1674
|
+
setInternalFlags(ipath, type_map);
|
|
1675
|
+
pynode = _graph.source(ipath.front());
|
|
1676
|
+
pxnode = _graph.target(ipath.back());
|
|
1677
|
+
|
|
1678
|
+
wnode = findPertinent(pynode, order_map, node_data,
|
|
1679
|
+
embed_arc, merge_roots);
|
|
1680
|
+
|
|
1681
|
+
// Minor-C
|
|
1682
|
+
{
|
|
1683
|
+
if (type_map[_graph.source(ipath.front())] == HIGHY) {
|
|
1684
|
+
if (type_map[_graph.target(ipath.back())] == HIGHX) {
|
|
1685
|
+
markFacePath(xnode, pxnode, order_map, node_data);
|
|
1686
|
+
}
|
|
1687
|
+
markFacePath(root, xnode, order_map, node_data);
|
|
1688
|
+
markPertinentPath(wnode, order_map, node_data, arc_lists,
|
|
1689
|
+
embed_arc, merge_roots);
|
|
1690
|
+
markInternalPath(ipath);
|
|
1691
|
+
int xlp = markExternalPath(xnode, order_map, child_lists,
|
|
1692
|
+
pred_map, ancestor_map, low_map);
|
|
1693
|
+
int ylp = markExternalPath(ynode, order_map, child_lists,
|
|
1694
|
+
pred_map, ancestor_map, low_map);
|
|
1695
|
+
markPredPath(root, order_list[xlp < ylp ? xlp : ylp], pred_map);
|
|
1696
|
+
return;
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
if (type_map[_graph.target(ipath.back())] == HIGHX) {
|
|
1700
|
+
markFacePath(ynode, root, order_map, node_data);
|
|
1701
|
+
markPertinentPath(wnode, order_map, node_data, arc_lists,
|
|
1702
|
+
embed_arc, merge_roots);
|
|
1703
|
+
markInternalPath(ipath);
|
|
1704
|
+
int xlp = markExternalPath(xnode, order_map, child_lists,
|
|
1705
|
+
pred_map, ancestor_map, low_map);
|
|
1706
|
+
int ylp = markExternalPath(ynode, order_map, child_lists,
|
|
1707
|
+
pred_map, ancestor_map, low_map);
|
|
1708
|
+
markPredPath(root, order_list[xlp < ylp ? xlp : ylp], pred_map);
|
|
1709
|
+
return;
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
std::vector<Arc> ppath;
|
|
1714
|
+
findPilePath(ppath, root, type_map, order_map, node_data, arc_lists);
|
|
1715
|
+
|
|
1716
|
+
// Minor-D
|
|
1717
|
+
if (!ppath.empty()) {
|
|
1718
|
+
markFacePath(ynode, xnode, order_map, node_data);
|
|
1719
|
+
markPertinentPath(wnode, order_map, node_data, arc_lists,
|
|
1720
|
+
embed_arc, merge_roots);
|
|
1721
|
+
markPilePath(ppath);
|
|
1722
|
+
markInternalPath(ipath);
|
|
1723
|
+
int xlp = markExternalPath(xnode, order_map, child_lists,
|
|
1724
|
+
pred_map, ancestor_map, low_map);
|
|
1725
|
+
int ylp = markExternalPath(ynode, order_map, child_lists,
|
|
1726
|
+
pred_map, ancestor_map, low_map);
|
|
1727
|
+
markPredPath(root, order_list[xlp < ylp ? xlp : ylp], pred_map);
|
|
1728
|
+
return;
|
|
1729
|
+
}
|
|
1730
|
+
|
|
1731
|
+
// Minor-E*
|
|
1732
|
+
{
|
|
1733
|
+
|
|
1734
|
+
if (!external(wnode, rorder, child_lists, ancestor_map, low_map)) {
|
|
1735
|
+
Node znode = findExternal(pynode, rorder, order_map,
|
|
1736
|
+
child_lists, ancestor_map,
|
|
1737
|
+
low_map, node_data);
|
|
1738
|
+
|
|
1739
|
+
if (type_map[znode] == LOWY) {
|
|
1740
|
+
markFacePath(root, xnode, order_map, node_data);
|
|
1741
|
+
markPertinentPath(wnode, order_map, node_data, arc_lists,
|
|
1742
|
+
embed_arc, merge_roots);
|
|
1743
|
+
markInternalPath(ipath);
|
|
1744
|
+
int xlp = markExternalPath(xnode, order_map, child_lists,
|
|
1745
|
+
pred_map, ancestor_map, low_map);
|
|
1746
|
+
int zlp = markExternalPath(znode, order_map, child_lists,
|
|
1747
|
+
pred_map, ancestor_map, low_map);
|
|
1748
|
+
markPredPath(root, order_list[xlp < zlp ? xlp : zlp], pred_map);
|
|
1749
|
+
} else {
|
|
1750
|
+
markFacePath(ynode, root, order_map, node_data);
|
|
1751
|
+
markPertinentPath(wnode, order_map, node_data, arc_lists,
|
|
1752
|
+
embed_arc, merge_roots);
|
|
1753
|
+
markInternalPath(ipath);
|
|
1754
|
+
int ylp = markExternalPath(ynode, order_map, child_lists,
|
|
1755
|
+
pred_map, ancestor_map, low_map);
|
|
1756
|
+
int zlp = markExternalPath(znode, order_map, child_lists,
|
|
1757
|
+
pred_map, ancestor_map, low_map);
|
|
1758
|
+
markPredPath(root, order_list[ylp < zlp ? ylp : zlp], pred_map);
|
|
1759
|
+
}
|
|
1760
|
+
return;
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
int xlp = markExternalPath(xnode, order_map, child_lists,
|
|
1764
|
+
pred_map, ancestor_map, low_map);
|
|
1765
|
+
int ylp = markExternalPath(ynode, order_map, child_lists,
|
|
1766
|
+
pred_map, ancestor_map, low_map);
|
|
1767
|
+
int wlp = markExternalPath(wnode, order_map, child_lists,
|
|
1768
|
+
pred_map, ancestor_map, low_map);
|
|
1769
|
+
|
|
1770
|
+
if (wlp > xlp && wlp > ylp) {
|
|
1771
|
+
markFacePath(root, root, order_map, node_data);
|
|
1772
|
+
markPredPath(root, order_list[xlp < ylp ? xlp : ylp], pred_map);
|
|
1773
|
+
return;
|
|
1774
|
+
}
|
|
1775
|
+
|
|
1776
|
+
markInternalPath(ipath);
|
|
1777
|
+
markPertinentPath(wnode, order_map, node_data, arc_lists,
|
|
1778
|
+
embed_arc, merge_roots);
|
|
1779
|
+
|
|
1780
|
+
if (xlp > ylp && xlp > wlp) {
|
|
1781
|
+
markFacePath(root, pynode, order_map, node_data);
|
|
1782
|
+
markFacePath(wnode, xnode, order_map, node_data);
|
|
1783
|
+
markPredPath(root, order_list[ylp < wlp ? ylp : wlp], pred_map);
|
|
1784
|
+
return;
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
if (ylp > xlp && ylp > wlp) {
|
|
1788
|
+
markFacePath(pxnode, root, order_map, node_data);
|
|
1789
|
+
markFacePath(ynode, wnode, order_map, node_data);
|
|
1790
|
+
markPredPath(root, order_list[xlp < wlp ? xlp : wlp], pred_map);
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
if (pynode != ynode) {
|
|
1795
|
+
markFacePath(pxnode, wnode, order_map, node_data);
|
|
1796
|
+
|
|
1797
|
+
int minlp = xlp < ylp ? xlp : ylp;
|
|
1798
|
+
if (wlp < minlp) minlp = wlp;
|
|
1799
|
+
|
|
1800
|
+
int maxlp = xlp > ylp ? xlp : ylp;
|
|
1801
|
+
if (wlp > maxlp) maxlp = wlp;
|
|
1802
|
+
|
|
1803
|
+
markPredPath(order_list[maxlp], order_list[minlp], pred_map);
|
|
1804
|
+
return;
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
if (pxnode != xnode) {
|
|
1808
|
+
markFacePath(wnode, pynode, order_map, node_data);
|
|
1809
|
+
|
|
1810
|
+
int minlp = xlp < ylp ? xlp : ylp;
|
|
1811
|
+
if (wlp < minlp) minlp = wlp;
|
|
1812
|
+
|
|
1813
|
+
int maxlp = xlp > ylp ? xlp : ylp;
|
|
1814
|
+
if (wlp > maxlp) maxlp = wlp;
|
|
1815
|
+
|
|
1816
|
+
markPredPath(order_list[maxlp], order_list[minlp], pred_map);
|
|
1817
|
+
return;
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
markFacePath(root, root, order_map, node_data);
|
|
1821
|
+
int minlp = xlp < ylp ? xlp : ylp;
|
|
1822
|
+
if (wlp < minlp) minlp = wlp;
|
|
1823
|
+
markPredPath(root, order_list[minlp], pred_map);
|
|
1824
|
+
return;
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
};
|
|
1830
|
+
|
|
1831
|
+
namespace _planarity_bits {
|
|
1832
|
+
|
|
1833
|
+
template <typename Graph, typename EmbeddingMap>
|
|
1834
|
+
void makeConnected(Graph& graph, EmbeddingMap& embedding) {
|
|
1835
|
+
DfsVisitor<Graph> null_visitor;
|
|
1836
|
+
DfsVisit<Graph, DfsVisitor<Graph> > dfs(graph, null_visitor);
|
|
1837
|
+
dfs.init();
|
|
1838
|
+
|
|
1839
|
+
typename Graph::Node u = INVALID;
|
|
1840
|
+
for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {
|
|
1841
|
+
if (!dfs.reached(n)) {
|
|
1842
|
+
dfs.addSource(n);
|
|
1843
|
+
dfs.start();
|
|
1844
|
+
if (u == INVALID) {
|
|
1845
|
+
u = n;
|
|
1846
|
+
} else {
|
|
1847
|
+
typename Graph::Node v = n;
|
|
1848
|
+
|
|
1849
|
+
typename Graph::Arc ue = typename Graph::OutArcIt(graph, u);
|
|
1850
|
+
typename Graph::Arc ve = typename Graph::OutArcIt(graph, v);
|
|
1851
|
+
|
|
1852
|
+
typename Graph::Arc e = graph.direct(graph.addEdge(u, v), true);
|
|
1853
|
+
|
|
1854
|
+
if (ue != INVALID) {
|
|
1855
|
+
embedding[e] = embedding[ue];
|
|
1856
|
+
embedding[ue] = e;
|
|
1857
|
+
} else {
|
|
1858
|
+
embedding[e] = e;
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
if (ve != INVALID) {
|
|
1862
|
+
embedding[graph.oppositeArc(e)] = embedding[ve];
|
|
1863
|
+
embedding[ve] = graph.oppositeArc(e);
|
|
1864
|
+
} else {
|
|
1865
|
+
embedding[graph.oppositeArc(e)] = graph.oppositeArc(e);
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
|
|
1872
|
+
template <typename Graph, typename EmbeddingMap>
|
|
1873
|
+
void makeBiNodeConnected(Graph& graph, EmbeddingMap& embedding) {
|
|
1874
|
+
typename Graph::template ArcMap<bool> processed(graph);
|
|
1875
|
+
|
|
1876
|
+
std::vector<typename Graph::Arc> arcs;
|
|
1877
|
+
for (typename Graph::ArcIt e(graph); e != INVALID; ++e) {
|
|
1878
|
+
arcs.push_back(e);
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
IterableBoolMap<Graph, typename Graph::Node> visited(graph, false);
|
|
1882
|
+
|
|
1883
|
+
for (int i = 0; i < int(arcs.size()); ++i) {
|
|
1884
|
+
typename Graph::Arc pp = arcs[i];
|
|
1885
|
+
if (processed[pp]) continue;
|
|
1886
|
+
|
|
1887
|
+
typename Graph::Arc e = embedding[graph.oppositeArc(pp)];
|
|
1888
|
+
processed[e] = true;
|
|
1889
|
+
visited.set(graph.source(e), true);
|
|
1890
|
+
|
|
1891
|
+
typename Graph::Arc p = e, l = e;
|
|
1892
|
+
e = embedding[graph.oppositeArc(e)];
|
|
1893
|
+
|
|
1894
|
+
while (e != l) {
|
|
1895
|
+
processed[e] = true;
|
|
1896
|
+
|
|
1897
|
+
if (visited[graph.source(e)]) {
|
|
1898
|
+
|
|
1899
|
+
typename Graph::Arc n =
|
|
1900
|
+
graph.direct(graph.addEdge(graph.source(p),
|
|
1901
|
+
graph.target(e)), true);
|
|
1902
|
+
embedding[n] = p;
|
|
1903
|
+
embedding[graph.oppositeArc(pp)] = n;
|
|
1904
|
+
|
|
1905
|
+
embedding[graph.oppositeArc(n)] =
|
|
1906
|
+
embedding[graph.oppositeArc(e)];
|
|
1907
|
+
embedding[graph.oppositeArc(e)] =
|
|
1908
|
+
graph.oppositeArc(n);
|
|
1909
|
+
|
|
1910
|
+
p = n;
|
|
1911
|
+
e = embedding[graph.oppositeArc(n)];
|
|
1912
|
+
} else {
|
|
1913
|
+
visited.set(graph.source(e), true);
|
|
1914
|
+
pp = p;
|
|
1915
|
+
p = e;
|
|
1916
|
+
e = embedding[graph.oppositeArc(e)];
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
visited.setAll(false);
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
|
|
1924
|
+
template <typename Graph, typename EmbeddingMap>
|
|
1925
|
+
void makeMaxPlanar(Graph& graph, EmbeddingMap& embedding) {
|
|
1926
|
+
|
|
1927
|
+
typename Graph::template NodeMap<int> degree(graph);
|
|
1928
|
+
|
|
1929
|
+
for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {
|
|
1930
|
+
degree[n] = countIncEdges(graph, n);
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1933
|
+
typename Graph::template ArcMap<bool> processed(graph);
|
|
1934
|
+
IterableBoolMap<Graph, typename Graph::Node> visited(graph, false);
|
|
1935
|
+
|
|
1936
|
+
std::vector<typename Graph::Arc> arcs;
|
|
1937
|
+
for (typename Graph::ArcIt e(graph); e != INVALID; ++e) {
|
|
1938
|
+
arcs.push_back(e);
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
for (int i = 0; i < int(arcs.size()); ++i) {
|
|
1942
|
+
typename Graph::Arc e = arcs[i];
|
|
1943
|
+
|
|
1944
|
+
if (processed[e]) continue;
|
|
1945
|
+
processed[e] = true;
|
|
1946
|
+
|
|
1947
|
+
typename Graph::Arc mine = e;
|
|
1948
|
+
int mind = degree[graph.source(e)];
|
|
1949
|
+
|
|
1950
|
+
int face_size = 1;
|
|
1951
|
+
|
|
1952
|
+
typename Graph::Arc l = e;
|
|
1953
|
+
e = embedding[graph.oppositeArc(e)];
|
|
1954
|
+
while (l != e) {
|
|
1955
|
+
processed[e] = true;
|
|
1956
|
+
|
|
1957
|
+
++face_size;
|
|
1958
|
+
|
|
1959
|
+
if (degree[graph.source(e)] < mind) {
|
|
1960
|
+
mine = e;
|
|
1961
|
+
mind = degree[graph.source(e)];
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1964
|
+
e = embedding[graph.oppositeArc(e)];
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
if (face_size < 4) {
|
|
1968
|
+
continue;
|
|
1969
|
+
}
|
|
1970
|
+
|
|
1971
|
+
typename Graph::Node s = graph.source(mine);
|
|
1972
|
+
for (typename Graph::OutArcIt e(graph, s); e != INVALID; ++e) {
|
|
1973
|
+
visited.set(graph.target(e), true);
|
|
1974
|
+
}
|
|
1975
|
+
|
|
1976
|
+
typename Graph::Arc oppe = INVALID;
|
|
1977
|
+
|
|
1978
|
+
e = embedding[graph.oppositeArc(mine)];
|
|
1979
|
+
e = embedding[graph.oppositeArc(e)];
|
|
1980
|
+
while (graph.target(e) != s) {
|
|
1981
|
+
if (visited[graph.source(e)]) {
|
|
1982
|
+
oppe = e;
|
|
1983
|
+
break;
|
|
1984
|
+
}
|
|
1985
|
+
e = embedding[graph.oppositeArc(e)];
|
|
1986
|
+
}
|
|
1987
|
+
visited.setAll(false);
|
|
1988
|
+
|
|
1989
|
+
if (oppe == INVALID) {
|
|
1990
|
+
|
|
1991
|
+
e = embedding[graph.oppositeArc(mine)];
|
|
1992
|
+
typename Graph::Arc pn = mine, p = e;
|
|
1993
|
+
|
|
1994
|
+
e = embedding[graph.oppositeArc(e)];
|
|
1995
|
+
while (graph.target(e) != s) {
|
|
1996
|
+
typename Graph::Arc n =
|
|
1997
|
+
graph.direct(graph.addEdge(s, graph.source(e)), true);
|
|
1998
|
+
|
|
1999
|
+
embedding[n] = pn;
|
|
2000
|
+
embedding[graph.oppositeArc(n)] = e;
|
|
2001
|
+
embedding[graph.oppositeArc(p)] = graph.oppositeArc(n);
|
|
2002
|
+
|
|
2003
|
+
pn = n;
|
|
2004
|
+
|
|
2005
|
+
p = e;
|
|
2006
|
+
e = embedding[graph.oppositeArc(e)];
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
embedding[graph.oppositeArc(e)] = pn;
|
|
2010
|
+
|
|
2011
|
+
} else {
|
|
2012
|
+
|
|
2013
|
+
mine = embedding[graph.oppositeArc(mine)];
|
|
2014
|
+
s = graph.source(mine);
|
|
2015
|
+
oppe = embedding[graph.oppositeArc(oppe)];
|
|
2016
|
+
typename Graph::Node t = graph.source(oppe);
|
|
2017
|
+
|
|
2018
|
+
typename Graph::Arc ce = graph.direct(graph.addEdge(s, t), true);
|
|
2019
|
+
embedding[ce] = mine;
|
|
2020
|
+
embedding[graph.oppositeArc(ce)] = oppe;
|
|
2021
|
+
|
|
2022
|
+
typename Graph::Arc pn = ce, p = oppe;
|
|
2023
|
+
e = embedding[graph.oppositeArc(oppe)];
|
|
2024
|
+
while (graph.target(e) != s) {
|
|
2025
|
+
typename Graph::Arc n =
|
|
2026
|
+
graph.direct(graph.addEdge(s, graph.source(e)), true);
|
|
2027
|
+
|
|
2028
|
+
embedding[n] = pn;
|
|
2029
|
+
embedding[graph.oppositeArc(n)] = e;
|
|
2030
|
+
embedding[graph.oppositeArc(p)] = graph.oppositeArc(n);
|
|
2031
|
+
|
|
2032
|
+
pn = n;
|
|
2033
|
+
|
|
2034
|
+
p = e;
|
|
2035
|
+
e = embedding[graph.oppositeArc(e)];
|
|
2036
|
+
|
|
2037
|
+
}
|
|
2038
|
+
embedding[graph.oppositeArc(e)] = pn;
|
|
2039
|
+
|
|
2040
|
+
pn = graph.oppositeArc(ce), p = mine;
|
|
2041
|
+
e = embedding[graph.oppositeArc(mine)];
|
|
2042
|
+
while (graph.target(e) != t) {
|
|
2043
|
+
typename Graph::Arc n =
|
|
2044
|
+
graph.direct(graph.addEdge(t, graph.source(e)), true);
|
|
2045
|
+
|
|
2046
|
+
embedding[n] = pn;
|
|
2047
|
+
embedding[graph.oppositeArc(n)] = e;
|
|
2048
|
+
embedding[graph.oppositeArc(p)] = graph.oppositeArc(n);
|
|
2049
|
+
|
|
2050
|
+
pn = n;
|
|
2051
|
+
|
|
2052
|
+
p = e;
|
|
2053
|
+
e = embedding[graph.oppositeArc(e)];
|
|
2054
|
+
|
|
2055
|
+
}
|
|
2056
|
+
embedding[graph.oppositeArc(e)] = pn;
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
}
|
|
2062
|
+
|
|
2063
|
+
/// \ingroup planar
|
|
2064
|
+
///
|
|
2065
|
+
/// \brief Schnyder's planar drawing algorithm
|
|
2066
|
+
///
|
|
2067
|
+
/// The planar drawing algorithm calculates positions for the nodes
|
|
2068
|
+
/// in the plane. These coordinates satisfy that if the edges are
|
|
2069
|
+
/// represented with straight lines, then they will not intersect
|
|
2070
|
+
/// each other.
|
|
2071
|
+
///
|
|
2072
|
+
/// Scnyder's algorithm embeds the graph on an \c (n-2)x(n-2) size grid,
|
|
2073
|
+
/// i.e. each node will be located in the \c [0..n-2]x[0..n-2] square.
|
|
2074
|
+
/// The time complexity of the algorithm is O(n).
|
|
2075
|
+
///
|
|
2076
|
+
/// \see PlanarEmbedding
|
|
2077
|
+
template <typename Graph>
|
|
2078
|
+
class PlanarDrawing {
|
|
2079
|
+
public:
|
|
2080
|
+
|
|
2081
|
+
TEMPLATE_GRAPH_TYPEDEFS(Graph);
|
|
2082
|
+
|
|
2083
|
+
/// \brief The point type for storing coordinates
|
|
2084
|
+
typedef dim2::Point<int> Point;
|
|
2085
|
+
/// \brief The map type for storing the coordinates of the nodes
|
|
2086
|
+
typedef typename Graph::template NodeMap<Point> PointMap;
|
|
2087
|
+
|
|
2088
|
+
|
|
2089
|
+
/// \brief Constructor
|
|
2090
|
+
///
|
|
2091
|
+
/// Constructor
|
|
2092
|
+
/// \pre The graph must be simple, i.e. it should not
|
|
2093
|
+
/// contain parallel or loop arcs.
|
|
2094
|
+
PlanarDrawing(const Graph& graph)
|
|
2095
|
+
: _graph(graph), _point_map(graph) {}
|
|
2096
|
+
|
|
2097
|
+
private:
|
|
2098
|
+
|
|
2099
|
+
template <typename AuxGraph, typename AuxEmbeddingMap>
|
|
2100
|
+
void drawing(const AuxGraph& graph,
|
|
2101
|
+
const AuxEmbeddingMap& next,
|
|
2102
|
+
PointMap& point_map) {
|
|
2103
|
+
TEMPLATE_GRAPH_TYPEDEFS(AuxGraph);
|
|
2104
|
+
|
|
2105
|
+
typename AuxGraph::template ArcMap<Arc> prev(graph);
|
|
2106
|
+
|
|
2107
|
+
for (NodeIt n(graph); n != INVALID; ++n) {
|
|
2108
|
+
Arc e = OutArcIt(graph, n);
|
|
2109
|
+
|
|
2110
|
+
Arc p = e, l = e;
|
|
2111
|
+
|
|
2112
|
+
e = next[e];
|
|
2113
|
+
while (e != l) {
|
|
2114
|
+
prev[e] = p;
|
|
2115
|
+
p = e;
|
|
2116
|
+
e = next[e];
|
|
2117
|
+
}
|
|
2118
|
+
prev[e] = p;
|
|
2119
|
+
}
|
|
2120
|
+
|
|
2121
|
+
Node anode, bnode, cnode;
|
|
2122
|
+
|
|
2123
|
+
{
|
|
2124
|
+
Arc e = ArcIt(graph);
|
|
2125
|
+
anode = graph.source(e);
|
|
2126
|
+
bnode = graph.target(e);
|
|
2127
|
+
cnode = graph.target(next[graph.oppositeArc(e)]);
|
|
2128
|
+
}
|
|
2129
|
+
|
|
2130
|
+
IterableBoolMap<AuxGraph, Node> proper(graph, false);
|
|
2131
|
+
typename AuxGraph::template NodeMap<int> conn(graph, -1);
|
|
2132
|
+
|
|
2133
|
+
conn[anode] = conn[bnode] = -2;
|
|
2134
|
+
{
|
|
2135
|
+
for (OutArcIt e(graph, anode); e != INVALID; ++e) {
|
|
2136
|
+
Node m = graph.target(e);
|
|
2137
|
+
if (conn[m] == -1) {
|
|
2138
|
+
conn[m] = 1;
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
conn[cnode] = 2;
|
|
2142
|
+
|
|
2143
|
+
for (OutArcIt e(graph, bnode); e != INVALID; ++e) {
|
|
2144
|
+
Node m = graph.target(e);
|
|
2145
|
+
if (conn[m] == -1) {
|
|
2146
|
+
conn[m] = 1;
|
|
2147
|
+
} else if (conn[m] != -2) {
|
|
2148
|
+
conn[m] += 1;
|
|
2149
|
+
Arc pe = graph.oppositeArc(e);
|
|
2150
|
+
if (conn[graph.target(next[pe])] == -2) {
|
|
2151
|
+
conn[m] -= 1;
|
|
2152
|
+
}
|
|
2153
|
+
if (conn[graph.target(prev[pe])] == -2) {
|
|
2154
|
+
conn[m] -= 1;
|
|
2155
|
+
}
|
|
2156
|
+
|
|
2157
|
+
proper.set(m, conn[m] == 1);
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2161
|
+
|
|
2162
|
+
|
|
2163
|
+
typename AuxGraph::template ArcMap<int> angle(graph, -1);
|
|
2164
|
+
|
|
2165
|
+
while (proper.trueNum() != 0) {
|
|
2166
|
+
Node n = typename IterableBoolMap<AuxGraph, Node>::TrueIt(proper);
|
|
2167
|
+
proper.set(n, false);
|
|
2168
|
+
conn[n] = -2;
|
|
2169
|
+
|
|
2170
|
+
for (OutArcIt e(graph, n); e != INVALID; ++e) {
|
|
2171
|
+
Node m = graph.target(e);
|
|
2172
|
+
if (conn[m] == -1) {
|
|
2173
|
+
conn[m] = 1;
|
|
2174
|
+
} else if (conn[m] != -2) {
|
|
2175
|
+
conn[m] += 1;
|
|
2176
|
+
Arc pe = graph.oppositeArc(e);
|
|
2177
|
+
if (conn[graph.target(next[pe])] == -2) {
|
|
2178
|
+
conn[m] -= 1;
|
|
2179
|
+
}
|
|
2180
|
+
if (conn[graph.target(prev[pe])] == -2) {
|
|
2181
|
+
conn[m] -= 1;
|
|
2182
|
+
}
|
|
2183
|
+
|
|
2184
|
+
proper.set(m, conn[m] == 1);
|
|
2185
|
+
}
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
{
|
|
2189
|
+
Arc e = OutArcIt(graph, n);
|
|
2190
|
+
Arc p = e, l = e;
|
|
2191
|
+
|
|
2192
|
+
e = next[e];
|
|
2193
|
+
while (e != l) {
|
|
2194
|
+
|
|
2195
|
+
if (conn[graph.target(e)] == -2 && conn[graph.target(p)] == -2) {
|
|
2196
|
+
Arc f = e;
|
|
2197
|
+
angle[f] = 0;
|
|
2198
|
+
f = next[graph.oppositeArc(f)];
|
|
2199
|
+
angle[f] = 1;
|
|
2200
|
+
f = next[graph.oppositeArc(f)];
|
|
2201
|
+
angle[f] = 2;
|
|
2202
|
+
}
|
|
2203
|
+
|
|
2204
|
+
p = e;
|
|
2205
|
+
e = next[e];
|
|
2206
|
+
}
|
|
2207
|
+
|
|
2208
|
+
if (conn[graph.target(e)] == -2 && conn[graph.target(p)] == -2) {
|
|
2209
|
+
Arc f = e;
|
|
2210
|
+
angle[f] = 0;
|
|
2211
|
+
f = next[graph.oppositeArc(f)];
|
|
2212
|
+
angle[f] = 1;
|
|
2213
|
+
f = next[graph.oppositeArc(f)];
|
|
2214
|
+
angle[f] = 2;
|
|
2215
|
+
}
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
|
|
2219
|
+
typename AuxGraph::template NodeMap<Node> apred(graph, INVALID);
|
|
2220
|
+
typename AuxGraph::template NodeMap<Node> bpred(graph, INVALID);
|
|
2221
|
+
typename AuxGraph::template NodeMap<Node> cpred(graph, INVALID);
|
|
2222
|
+
|
|
2223
|
+
typename AuxGraph::template NodeMap<int> apredid(graph, -1);
|
|
2224
|
+
typename AuxGraph::template NodeMap<int> bpredid(graph, -1);
|
|
2225
|
+
typename AuxGraph::template NodeMap<int> cpredid(graph, -1);
|
|
2226
|
+
|
|
2227
|
+
for (ArcIt e(graph); e != INVALID; ++e) {
|
|
2228
|
+
if (angle[e] == angle[next[e]]) {
|
|
2229
|
+
switch (angle[e]) {
|
|
2230
|
+
case 2:
|
|
2231
|
+
apred[graph.target(e)] = graph.source(e);
|
|
2232
|
+
apredid[graph.target(e)] = graph.id(graph.source(e));
|
|
2233
|
+
break;
|
|
2234
|
+
case 1:
|
|
2235
|
+
bpred[graph.target(e)] = graph.source(e);
|
|
2236
|
+
bpredid[graph.target(e)] = graph.id(graph.source(e));
|
|
2237
|
+
break;
|
|
2238
|
+
case 0:
|
|
2239
|
+
cpred[graph.target(e)] = graph.source(e);
|
|
2240
|
+
cpredid[graph.target(e)] = graph.id(graph.source(e));
|
|
2241
|
+
break;
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
}
|
|
2245
|
+
|
|
2246
|
+
cpred[anode] = INVALID;
|
|
2247
|
+
cpred[bnode] = INVALID;
|
|
2248
|
+
|
|
2249
|
+
std::vector<Node> aorder, border, corder;
|
|
2250
|
+
|
|
2251
|
+
{
|
|
2252
|
+
typename AuxGraph::template NodeMap<bool> processed(graph, false);
|
|
2253
|
+
std::vector<Node> st;
|
|
2254
|
+
for (NodeIt n(graph); n != INVALID; ++n) {
|
|
2255
|
+
if (!processed[n] && n != bnode && n != cnode) {
|
|
2256
|
+
st.push_back(n);
|
|
2257
|
+
processed[n] = true;
|
|
2258
|
+
Node m = apred[n];
|
|
2259
|
+
while (m != INVALID && !processed[m]) {
|
|
2260
|
+
st.push_back(m);
|
|
2261
|
+
processed[m] = true;
|
|
2262
|
+
m = apred[m];
|
|
2263
|
+
}
|
|
2264
|
+
while (!st.empty()) {
|
|
2265
|
+
aorder.push_back(st.back());
|
|
2266
|
+
st.pop_back();
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2271
|
+
|
|
2272
|
+
{
|
|
2273
|
+
typename AuxGraph::template NodeMap<bool> processed(graph, false);
|
|
2274
|
+
std::vector<Node> st;
|
|
2275
|
+
for (NodeIt n(graph); n != INVALID; ++n) {
|
|
2276
|
+
if (!processed[n] && n != cnode && n != anode) {
|
|
2277
|
+
st.push_back(n);
|
|
2278
|
+
processed[n] = true;
|
|
2279
|
+
Node m = bpred[n];
|
|
2280
|
+
while (m != INVALID && !processed[m]) {
|
|
2281
|
+
st.push_back(m);
|
|
2282
|
+
processed[m] = true;
|
|
2283
|
+
m = bpred[m];
|
|
2284
|
+
}
|
|
2285
|
+
while (!st.empty()) {
|
|
2286
|
+
border.push_back(st.back());
|
|
2287
|
+
st.pop_back();
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
|
|
2293
|
+
{
|
|
2294
|
+
typename AuxGraph::template NodeMap<bool> processed(graph, false);
|
|
2295
|
+
std::vector<Node> st;
|
|
2296
|
+
for (NodeIt n(graph); n != INVALID; ++n) {
|
|
2297
|
+
if (!processed[n] && n != anode && n != bnode) {
|
|
2298
|
+
st.push_back(n);
|
|
2299
|
+
processed[n] = true;
|
|
2300
|
+
Node m = cpred[n];
|
|
2301
|
+
while (m != INVALID && !processed[m]) {
|
|
2302
|
+
st.push_back(m);
|
|
2303
|
+
processed[m] = true;
|
|
2304
|
+
m = cpred[m];
|
|
2305
|
+
}
|
|
2306
|
+
while (!st.empty()) {
|
|
2307
|
+
corder.push_back(st.back());
|
|
2308
|
+
st.pop_back();
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
|
|
2314
|
+
typename AuxGraph::template NodeMap<int> atree(graph, 0);
|
|
2315
|
+
for (int i = aorder.size() - 1; i >= 0; --i) {
|
|
2316
|
+
Node n = aorder[i];
|
|
2317
|
+
atree[n] = 1;
|
|
2318
|
+
for (OutArcIt e(graph, n); e != INVALID; ++e) {
|
|
2319
|
+
if (apred[graph.target(e)] == n) {
|
|
2320
|
+
atree[n] += atree[graph.target(e)];
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
}
|
|
2324
|
+
|
|
2325
|
+
typename AuxGraph::template NodeMap<int> btree(graph, 0);
|
|
2326
|
+
for (int i = border.size() - 1; i >= 0; --i) {
|
|
2327
|
+
Node n = border[i];
|
|
2328
|
+
btree[n] = 1;
|
|
2329
|
+
for (OutArcIt e(graph, n); e != INVALID; ++e) {
|
|
2330
|
+
if (bpred[graph.target(e)] == n) {
|
|
2331
|
+
btree[n] += btree[graph.target(e)];
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2335
|
+
|
|
2336
|
+
typename AuxGraph::template NodeMap<int> apath(graph, 0);
|
|
2337
|
+
apath[bnode] = apath[cnode] = 1;
|
|
2338
|
+
typename AuxGraph::template NodeMap<int> apath_btree(graph, 0);
|
|
2339
|
+
apath_btree[bnode] = btree[bnode];
|
|
2340
|
+
for (int i = 1; i < int(aorder.size()); ++i) {
|
|
2341
|
+
Node n = aorder[i];
|
|
2342
|
+
apath[n] = apath[apred[n]] + 1;
|
|
2343
|
+
apath_btree[n] = btree[n] + apath_btree[apred[n]];
|
|
2344
|
+
}
|
|
2345
|
+
|
|
2346
|
+
typename AuxGraph::template NodeMap<int> bpath_atree(graph, 0);
|
|
2347
|
+
bpath_atree[anode] = atree[anode];
|
|
2348
|
+
for (int i = 1; i < int(border.size()); ++i) {
|
|
2349
|
+
Node n = border[i];
|
|
2350
|
+
bpath_atree[n] = atree[n] + bpath_atree[bpred[n]];
|
|
2351
|
+
}
|
|
2352
|
+
|
|
2353
|
+
typename AuxGraph::template NodeMap<int> cpath(graph, 0);
|
|
2354
|
+
cpath[anode] = cpath[bnode] = 1;
|
|
2355
|
+
typename AuxGraph::template NodeMap<int> cpath_atree(graph, 0);
|
|
2356
|
+
cpath_atree[anode] = atree[anode];
|
|
2357
|
+
typename AuxGraph::template NodeMap<int> cpath_btree(graph, 0);
|
|
2358
|
+
cpath_btree[bnode] = btree[bnode];
|
|
2359
|
+
for (int i = 1; i < int(corder.size()); ++i) {
|
|
2360
|
+
Node n = corder[i];
|
|
2361
|
+
cpath[n] = cpath[cpred[n]] + 1;
|
|
2362
|
+
cpath_atree[n] = atree[n] + cpath_atree[cpred[n]];
|
|
2363
|
+
cpath_btree[n] = btree[n] + cpath_btree[cpred[n]];
|
|
2364
|
+
}
|
|
2365
|
+
|
|
2366
|
+
typename AuxGraph::template NodeMap<int> third(graph);
|
|
2367
|
+
for (NodeIt n(graph); n != INVALID; ++n) {
|
|
2368
|
+
point_map[n].x =
|
|
2369
|
+
bpath_atree[n] + cpath_atree[n] - atree[n] - cpath[n] + 1;
|
|
2370
|
+
point_map[n].y =
|
|
2371
|
+
cpath_btree[n] + apath_btree[n] - btree[n] - apath[n] + 1;
|
|
2372
|
+
}
|
|
2373
|
+
|
|
2374
|
+
}
|
|
2375
|
+
|
|
2376
|
+
public:
|
|
2377
|
+
|
|
2378
|
+
/// \brief Calculate the node positions
|
|
2379
|
+
///
|
|
2380
|
+
/// This function calculates the node positions on the plane.
|
|
2381
|
+
/// \return \c true if the graph is planar.
|
|
2382
|
+
bool run() {
|
|
2383
|
+
PlanarEmbedding<Graph> pe(_graph);
|
|
2384
|
+
if (!pe.run()) return false;
|
|
2385
|
+
|
|
2386
|
+
run(pe);
|
|
2387
|
+
return true;
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2390
|
+
/// \brief Calculate the node positions according to a
|
|
2391
|
+
/// combinatorical embedding
|
|
2392
|
+
///
|
|
2393
|
+
/// This function calculates the node positions on the plane.
|
|
2394
|
+
/// The given \c embedding map should contain a valid combinatorical
|
|
2395
|
+
/// embedding, i.e. a valid cyclic order of the arcs.
|
|
2396
|
+
/// It can be computed using PlanarEmbedding.
|
|
2397
|
+
template <typename EmbeddingMap>
|
|
2398
|
+
void run(const EmbeddingMap& embedding) {
|
|
2399
|
+
typedef SmartEdgeSet<Graph> AuxGraph;
|
|
2400
|
+
|
|
2401
|
+
if (3 * countNodes(_graph) - 6 == countEdges(_graph)) {
|
|
2402
|
+
drawing(_graph, embedding, _point_map);
|
|
2403
|
+
return;
|
|
2404
|
+
}
|
|
2405
|
+
|
|
2406
|
+
AuxGraph aux_graph(_graph);
|
|
2407
|
+
typename AuxGraph::template ArcMap<typename AuxGraph::Arc>
|
|
2408
|
+
aux_embedding(aux_graph);
|
|
2409
|
+
|
|
2410
|
+
{
|
|
2411
|
+
|
|
2412
|
+
typename Graph::template EdgeMap<typename AuxGraph::Edge>
|
|
2413
|
+
ref(_graph);
|
|
2414
|
+
|
|
2415
|
+
for (EdgeIt e(_graph); e != INVALID; ++e) {
|
|
2416
|
+
ref[e] = aux_graph.addEdge(_graph.u(e), _graph.v(e));
|
|
2417
|
+
}
|
|
2418
|
+
|
|
2419
|
+
for (EdgeIt e(_graph); e != INVALID; ++e) {
|
|
2420
|
+
Arc ee = embedding[_graph.direct(e, true)];
|
|
2421
|
+
aux_embedding[aux_graph.direct(ref[e], true)] =
|
|
2422
|
+
aux_graph.direct(ref[ee], _graph.direction(ee));
|
|
2423
|
+
ee = embedding[_graph.direct(e, false)];
|
|
2424
|
+
aux_embedding[aux_graph.direct(ref[e], false)] =
|
|
2425
|
+
aux_graph.direct(ref[ee], _graph.direction(ee));
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
_planarity_bits::makeConnected(aux_graph, aux_embedding);
|
|
2429
|
+
_planarity_bits::makeBiNodeConnected(aux_graph, aux_embedding);
|
|
2430
|
+
_planarity_bits::makeMaxPlanar(aux_graph, aux_embedding);
|
|
2431
|
+
drawing(aux_graph, aux_embedding, _point_map);
|
|
2432
|
+
}
|
|
2433
|
+
|
|
2434
|
+
/// \brief The coordinate of the given node
|
|
2435
|
+
///
|
|
2436
|
+
/// This function returns the coordinate of the given node.
|
|
2437
|
+
Point operator[](const Node& node) const {
|
|
2438
|
+
return _point_map[node];
|
|
2439
|
+
}
|
|
2440
|
+
|
|
2441
|
+
/// \brief Return the grid embedding in a node map
|
|
2442
|
+
///
|
|
2443
|
+
/// This function returns the grid embedding in a node map of
|
|
2444
|
+
/// \c dim2::Point<int> coordinates.
|
|
2445
|
+
const PointMap& coords() const {
|
|
2446
|
+
return _point_map;
|
|
2447
|
+
}
|
|
2448
|
+
|
|
2449
|
+
private:
|
|
2450
|
+
|
|
2451
|
+
const Graph& _graph;
|
|
2452
|
+
PointMap _point_map;
|
|
2453
|
+
|
|
2454
|
+
};
|
|
2455
|
+
|
|
2456
|
+
namespace _planarity_bits {
|
|
2457
|
+
|
|
2458
|
+
template <typename ColorMap>
|
|
2459
|
+
class KempeFilter {
|
|
2460
|
+
public:
|
|
2461
|
+
typedef typename ColorMap::Key Key;
|
|
2462
|
+
typedef bool Value;
|
|
2463
|
+
|
|
2464
|
+
KempeFilter(const ColorMap& color_map,
|
|
2465
|
+
const typename ColorMap::Value& first,
|
|
2466
|
+
const typename ColorMap::Value& second)
|
|
2467
|
+
: _color_map(color_map), _first(first), _second(second) {}
|
|
2468
|
+
|
|
2469
|
+
Value operator[](const Key& key) const {
|
|
2470
|
+
return _color_map[key] == _first || _color_map[key] == _second;
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2473
|
+
private:
|
|
2474
|
+
const ColorMap& _color_map;
|
|
2475
|
+
typename ColorMap::Value _first, _second;
|
|
2476
|
+
};
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2479
|
+
/// \ingroup planar
|
|
2480
|
+
///
|
|
2481
|
+
/// \brief Coloring planar graphs
|
|
2482
|
+
///
|
|
2483
|
+
/// The graph coloring problem is the coloring of the graph nodes
|
|
2484
|
+
/// so that there are no adjacent nodes with the same color. The
|
|
2485
|
+
/// planar graphs can always be colored with four colors, which is
|
|
2486
|
+
/// proved by Appel and Haken. Their proofs provide a quadratic
|
|
2487
|
+
/// time algorithm for four coloring, but it could not be used to
|
|
2488
|
+
/// implement an efficient algorithm. The five and six coloring can be
|
|
2489
|
+
/// made in linear time, but in this class, the five coloring has
|
|
2490
|
+
/// quadratic worst case time complexity. The two coloring (if
|
|
2491
|
+
/// possible) is solvable with a graph search algorithm and it is
|
|
2492
|
+
/// implemented in \ref bipartitePartitions() function in LEMON. To
|
|
2493
|
+
/// decide whether a planar graph is three colorable is NP-complete.
|
|
2494
|
+
///
|
|
2495
|
+
/// This class contains member functions for calculate colorings
|
|
2496
|
+
/// with five and six colors. The six coloring algorithm is a simple
|
|
2497
|
+
/// greedy coloring on the backward minimum outgoing order of nodes.
|
|
2498
|
+
/// This order can be computed by selecting the node with least
|
|
2499
|
+
/// outgoing arcs to unprocessed nodes in each phase. This order
|
|
2500
|
+
/// guarantees that when a node is chosen for coloring it has at
|
|
2501
|
+
/// most five already colored adjacents. The five coloring algorithm
|
|
2502
|
+
/// use the same method, but if the greedy approach fails to color
|
|
2503
|
+
/// with five colors, i.e. the node has five already different
|
|
2504
|
+
/// colored neighbours, it swaps the colors in one of the connected
|
|
2505
|
+
/// two colored sets with the Kempe recoloring method.
|
|
2506
|
+
template <typename Graph>
|
|
2507
|
+
class PlanarColoring {
|
|
2508
|
+
public:
|
|
2509
|
+
|
|
2510
|
+
TEMPLATE_GRAPH_TYPEDEFS(Graph);
|
|
2511
|
+
|
|
2512
|
+
/// \brief The map type for storing color indices
|
|
2513
|
+
typedef typename Graph::template NodeMap<int> IndexMap;
|
|
2514
|
+
/// \brief The map type for storing colors
|
|
2515
|
+
///
|
|
2516
|
+
/// The map type for storing colors.
|
|
2517
|
+
/// \see Palette, Color
|
|
2518
|
+
typedef ComposeMap<Palette, IndexMap> ColorMap;
|
|
2519
|
+
|
|
2520
|
+
/// \brief Constructor
|
|
2521
|
+
///
|
|
2522
|
+
/// Constructor.
|
|
2523
|
+
/// \pre The graph must be simple, i.e. it should not
|
|
2524
|
+
/// contain parallel or loop arcs.
|
|
2525
|
+
PlanarColoring(const Graph& graph)
|
|
2526
|
+
: _graph(graph), _color_map(graph), _palette(0) {
|
|
2527
|
+
_palette.add(Color(1,0,0));
|
|
2528
|
+
_palette.add(Color(0,1,0));
|
|
2529
|
+
_palette.add(Color(0,0,1));
|
|
2530
|
+
_palette.add(Color(1,1,0));
|
|
2531
|
+
_palette.add(Color(1,0,1));
|
|
2532
|
+
_palette.add(Color(0,1,1));
|
|
2533
|
+
}
|
|
2534
|
+
|
|
2535
|
+
/// \brief Return the node map of color indices
|
|
2536
|
+
///
|
|
2537
|
+
/// This function returns the node map of color indices. The values are
|
|
2538
|
+
/// in the range \c [0..4] or \c [0..5] according to the coloring method.
|
|
2539
|
+
IndexMap colorIndexMap() const {
|
|
2540
|
+
return _color_map;
|
|
2541
|
+
}
|
|
2542
|
+
|
|
2543
|
+
/// \brief Return the node map of colors
|
|
2544
|
+
///
|
|
2545
|
+
/// This function returns the node map of colors. The values are among
|
|
2546
|
+
/// five or six distinct \ref lemon::Color "colors".
|
|
2547
|
+
ColorMap colorMap() const {
|
|
2548
|
+
return composeMap(_palette, _color_map);
|
|
2549
|
+
}
|
|
2550
|
+
|
|
2551
|
+
/// \brief Return the color index of the node
|
|
2552
|
+
///
|
|
2553
|
+
/// This function returns the color index of the given node. The value is
|
|
2554
|
+
/// in the range \c [0..4] or \c [0..5] according to the coloring method.
|
|
2555
|
+
int colorIndex(const Node& node) const {
|
|
2556
|
+
return _color_map[node];
|
|
2557
|
+
}
|
|
2558
|
+
|
|
2559
|
+
/// \brief Return the color of the node
|
|
2560
|
+
///
|
|
2561
|
+
/// This function returns the color of the given node. The value is among
|
|
2562
|
+
/// five or six distinct \ref lemon::Color "colors".
|
|
2563
|
+
Color color(const Node& node) const {
|
|
2564
|
+
return _palette[_color_map[node]];
|
|
2565
|
+
}
|
|
2566
|
+
|
|
2567
|
+
|
|
2568
|
+
/// \brief Calculate a coloring with at most six colors
|
|
2569
|
+
///
|
|
2570
|
+
/// This function calculates a coloring with at most six colors. The time
|
|
2571
|
+
/// complexity of this variant is linear in the size of the graph.
|
|
2572
|
+
/// \return \c true if the algorithm could color the graph with six colors.
|
|
2573
|
+
/// If the algorithm fails, then the graph is not planar.
|
|
2574
|
+
/// \note This function can return \c true if the graph is not
|
|
2575
|
+
/// planar, but it can be colored with at most six colors.
|
|
2576
|
+
bool runSixColoring() {
|
|
2577
|
+
|
|
2578
|
+
typename Graph::template NodeMap<int> heap_index(_graph, -1);
|
|
2579
|
+
BucketHeap<typename Graph::template NodeMap<int> > heap(heap_index);
|
|
2580
|
+
|
|
2581
|
+
for (NodeIt n(_graph); n != INVALID; ++n) {
|
|
2582
|
+
_color_map[n] = -2;
|
|
2583
|
+
heap.push(n, countOutArcs(_graph, n));
|
|
2584
|
+
}
|
|
2585
|
+
|
|
2586
|
+
std::vector<Node> order;
|
|
2587
|
+
|
|
2588
|
+
while (!heap.empty()) {
|
|
2589
|
+
Node n = heap.top();
|
|
2590
|
+
heap.pop();
|
|
2591
|
+
_color_map[n] = -1;
|
|
2592
|
+
order.push_back(n);
|
|
2593
|
+
for (OutArcIt e(_graph, n); e != INVALID; ++e) {
|
|
2594
|
+
Node t = _graph.runningNode(e);
|
|
2595
|
+
if (_color_map[t] == -2) {
|
|
2596
|
+
heap.decrease(t, heap[t] - 1);
|
|
2597
|
+
}
|
|
2598
|
+
}
|
|
2599
|
+
}
|
|
2600
|
+
|
|
2601
|
+
for (int i = order.size() - 1; i >= 0; --i) {
|
|
2602
|
+
std::vector<bool> forbidden(6, false);
|
|
2603
|
+
for (OutArcIt e(_graph, order[i]); e != INVALID; ++e) {
|
|
2604
|
+
Node t = _graph.runningNode(e);
|
|
2605
|
+
if (_color_map[t] != -1) {
|
|
2606
|
+
forbidden[_color_map[t]] = true;
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
for (int k = 0; k < 6; ++k) {
|
|
2610
|
+
if (!forbidden[k]) {
|
|
2611
|
+
_color_map[order[i]] = k;
|
|
2612
|
+
break;
|
|
2613
|
+
}
|
|
2614
|
+
}
|
|
2615
|
+
if (_color_map[order[i]] == -1) {
|
|
2616
|
+
return false;
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
return true;
|
|
2620
|
+
}
|
|
2621
|
+
|
|
2622
|
+
private:
|
|
2623
|
+
|
|
2624
|
+
bool recolor(const Node& u, const Node& v) {
|
|
2625
|
+
int ucolor = _color_map[u];
|
|
2626
|
+
int vcolor = _color_map[v];
|
|
2627
|
+
typedef _planarity_bits::KempeFilter<IndexMap> KempeFilter;
|
|
2628
|
+
KempeFilter filter(_color_map, ucolor, vcolor);
|
|
2629
|
+
|
|
2630
|
+
typedef FilterNodes<const Graph, const KempeFilter> KempeGraph;
|
|
2631
|
+
KempeGraph kempe_graph(_graph, filter);
|
|
2632
|
+
|
|
2633
|
+
std::vector<Node> comp;
|
|
2634
|
+
Bfs<KempeGraph> bfs(kempe_graph);
|
|
2635
|
+
bfs.init();
|
|
2636
|
+
bfs.addSource(u);
|
|
2637
|
+
while (!bfs.emptyQueue()) {
|
|
2638
|
+
Node n = bfs.nextNode();
|
|
2639
|
+
if (n == v) return false;
|
|
2640
|
+
comp.push_back(n);
|
|
2641
|
+
bfs.processNextNode();
|
|
2642
|
+
}
|
|
2643
|
+
|
|
2644
|
+
int scolor = ucolor + vcolor;
|
|
2645
|
+
for (int i = 0; i < static_cast<int>(comp.size()); ++i) {
|
|
2646
|
+
_color_map[comp[i]] = scolor - _color_map[comp[i]];
|
|
2647
|
+
}
|
|
2648
|
+
|
|
2649
|
+
return true;
|
|
2650
|
+
}
|
|
2651
|
+
|
|
2652
|
+
template <typename EmbeddingMap>
|
|
2653
|
+
void kempeRecoloring(const Node& node, const EmbeddingMap& embedding) {
|
|
2654
|
+
std::vector<Node> nodes;
|
|
2655
|
+
nodes.reserve(4);
|
|
2656
|
+
|
|
2657
|
+
for (Arc e = OutArcIt(_graph, node); e != INVALID; e = embedding[e]) {
|
|
2658
|
+
Node t = _graph.target(e);
|
|
2659
|
+
if (_color_map[t] != -1) {
|
|
2660
|
+
nodes.push_back(t);
|
|
2661
|
+
if (nodes.size() == 4) break;
|
|
2662
|
+
}
|
|
2663
|
+
}
|
|
2664
|
+
|
|
2665
|
+
int color = _color_map[nodes[0]];
|
|
2666
|
+
if (recolor(nodes[0], nodes[2])) {
|
|
2667
|
+
_color_map[node] = color;
|
|
2668
|
+
} else {
|
|
2669
|
+
color = _color_map[nodes[1]];
|
|
2670
|
+
recolor(nodes[1], nodes[3]);
|
|
2671
|
+
_color_map[node] = color;
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2674
|
+
|
|
2675
|
+
public:
|
|
2676
|
+
|
|
2677
|
+
/// \brief Calculate a coloring with at most five colors
|
|
2678
|
+
///
|
|
2679
|
+
/// This function calculates a coloring with at most five
|
|
2680
|
+
/// colors. The worst case time complexity of this variant is
|
|
2681
|
+
/// quadratic in the size of the graph.
|
|
2682
|
+
/// \param embedding This map should contain a valid combinatorical
|
|
2683
|
+
/// embedding, i.e. a valid cyclic order of the arcs.
|
|
2684
|
+
/// It can be computed using PlanarEmbedding.
|
|
2685
|
+
template <typename EmbeddingMap>
|
|
2686
|
+
void runFiveColoring(const EmbeddingMap& embedding) {
|
|
2687
|
+
|
|
2688
|
+
typename Graph::template NodeMap<int> heap_index(_graph, -1);
|
|
2689
|
+
BucketHeap<typename Graph::template NodeMap<int> > heap(heap_index);
|
|
2690
|
+
|
|
2691
|
+
for (NodeIt n(_graph); n != INVALID; ++n) {
|
|
2692
|
+
_color_map[n] = -2;
|
|
2693
|
+
heap.push(n, countOutArcs(_graph, n));
|
|
2694
|
+
}
|
|
2695
|
+
|
|
2696
|
+
std::vector<Node> order;
|
|
2697
|
+
|
|
2698
|
+
while (!heap.empty()) {
|
|
2699
|
+
Node n = heap.top();
|
|
2700
|
+
heap.pop();
|
|
2701
|
+
_color_map[n] = -1;
|
|
2702
|
+
order.push_back(n);
|
|
2703
|
+
for (OutArcIt e(_graph, n); e != INVALID; ++e) {
|
|
2704
|
+
Node t = _graph.runningNode(e);
|
|
2705
|
+
if (_color_map[t] == -2) {
|
|
2706
|
+
heap.decrease(t, heap[t] - 1);
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2709
|
+
}
|
|
2710
|
+
|
|
2711
|
+
for (int i = order.size() - 1; i >= 0; --i) {
|
|
2712
|
+
std::vector<bool> forbidden(5, false);
|
|
2713
|
+
for (OutArcIt e(_graph, order[i]); e != INVALID; ++e) {
|
|
2714
|
+
Node t = _graph.runningNode(e);
|
|
2715
|
+
if (_color_map[t] != -1) {
|
|
2716
|
+
forbidden[_color_map[t]] = true;
|
|
2717
|
+
}
|
|
2718
|
+
}
|
|
2719
|
+
for (int k = 0; k < 5; ++k) {
|
|
2720
|
+
if (!forbidden[k]) {
|
|
2721
|
+
_color_map[order[i]] = k;
|
|
2722
|
+
break;
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
if (_color_map[order[i]] == -1) {
|
|
2726
|
+
kempeRecoloring(order[i], embedding);
|
|
2727
|
+
}
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2730
|
+
|
|
2731
|
+
/// \brief Calculate a coloring with at most five colors
|
|
2732
|
+
///
|
|
2733
|
+
/// This function calculates a coloring with at most five
|
|
2734
|
+
/// colors. The worst case time complexity of this variant is
|
|
2735
|
+
/// quadratic in the size of the graph.
|
|
2736
|
+
/// \return \c true if the graph is planar.
|
|
2737
|
+
bool runFiveColoring() {
|
|
2738
|
+
PlanarEmbedding<Graph> pe(_graph);
|
|
2739
|
+
if (!pe.run()) return false;
|
|
2740
|
+
|
|
2741
|
+
runFiveColoring(pe.embeddingMap());
|
|
2742
|
+
return true;
|
|
2743
|
+
}
|
|
2744
|
+
|
|
2745
|
+
private:
|
|
2746
|
+
|
|
2747
|
+
const Graph& _graph;
|
|
2748
|
+
IndexMap _color_map;
|
|
2749
|
+
Palette _palette;
|
|
2750
|
+
};
|
|
2751
|
+
|
|
2752
|
+
}
|
|
2753
|
+
|
|
2754
|
+
#endif
|