diff --git a/doc/figs/planar_vertex_coloring_with_5.png b/doc/figs/planar_vertex_coloring_with_5.png
new file mode 100644
index 000000000..729083cf1
Binary files /dev/null and b/doc/figs/planar_vertex_coloring_with_5.png differ
diff --git a/doc/planar_vertex_six_coloring.html b/doc/planar_vertex_six_coloring.html
new file mode 100644
index 000000000..15465b1ef
--- /dev/null
+++ b/doc/planar_vertex_six_coloring.html
@@ -0,0 +1,101 @@
+
+
+
+
+ Boost Graph Library: Planar Vertex Six Coloring
+
+
+
+
+planar_vertex_six_coloring
+
+
+
+template<class VertexListGraph, class ColorMap>
+typename property_traits<ColorMap>::value_type
+planar_vertex_six_coloring(const VertexListGraph& g, ColorMap color);
+
+
+Computes a vertex coloring for
+the vertices in the planar graph in linear time, using at most 6 colors.
+Planar graphs can always be vertex colored with 4 colors, there
+is a quadratic time algorithm.
+Boost sequential_vertex_coloring can be forced to use any number k of colors for a crafted planar graph (first test graph).
+
+
Here is the vertex coloring with 5 colors determined for icosahedron.
+
+
+
+
Planar graphs with n vertices have at most 3n-6 edges. Therefore always a vertex of degree ≤5 exists. Algorithm removes such "small" vertices until the graph becomes empty. Then the vertices are colored in reverse order they were removed, with the smallest color different to its at most 5 neighbors when it was removed. Therefore at most 6 colors are needed.
+
+
Where Defined
+boost/graph/planar_vertex_six_coloring.hpp
+
+Parameters
+IN: const Graph& g
+
+ The graph object on which the algorithm will be applied. The type
+ Graph must be a model of Vertex List Graph and Adjacency Graph.
+
+
+OUT: ColorMap color
+
+ This property map records the colors of each vertex. It must be a
+ model of
+ Writeable
+ Property Map whose key type is the same as the vertex descriptor
+ type of the graph and whose value type is an integral type that can
+ store all values of the graph's vertices_size_type.
+
+
+Complexity
+
+The time complexity is O(V), where V is the
+number of vertices of the planar graph.
+This runtime is only possible using undirected_graph_constant_time_edge_add_and_remove providing O(1) remove_edge().
+
+Example
+boost/graph/example/planar_vertex_six_coloring.cpp
+
+
+ template< class graph > void simple_maximal_planar_random_graph(graph& g, int n); // see example
+ typedef adjacency_list< listS, vecS, undirectedS > Graph;
+ typedef graph_traits< Graph >::vertices_size_type vertices_size_type;
+
+ Graph g;
+ simple_maximal_planar_random_graph(g, 1000000);
+
+ std::vector< vertices_size_type > color_vec(num_vertices(g));
+ auto color = make_container_vertex_map(color_vec, g);
+ vertices_size_type num_colors = planar_vertex_six_coloring(g, color);
+
+
+Test
+boost/graph/test/planar_vertex_six_coloring.cpp test determines vertex coloring for three planar graphs:
+
+- "Fibonacci graph" (for k=15), with fib(k+1) vertices and fib(k+2)-2 edges
+
- boost/graph/test/planar_input_graphs/pentakis_dodecahedron.leda
+
- boost/graph/test/planar_input_graphs/maximal_planar_1000.leda
+
+With 15/5/6 colors used by sequential_vertex_coloring() and 6/4/6 colors used by planar_vertex_six_coloring().
+
+
+
+
+
+
+
diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html
index 5eb527ac1..8fe5d98e2 100644
--- a/doc/table_of_contents.html
+++ b/doc/table_of_contents.html
@@ -104,6 +104,9 @@ adjacency_matrix
compressed_sparse_row_graph
@@ -286,6 +289,8 @@ Table of Contents: the Boost Graph Library
make_biconnected_planar
make_maximal_planar
+
+ planar_vertex_six_coloring
Miscellaneous Algorithms
diff --git a/doc/undirected_graph_constant_time_edge_add_and_remove.html b/doc/undirected_graph_constant_time_edge_add_and_remove.html
new file mode 100644
index 000000000..332651f95
--- /dev/null
+++ b/doc/undirected_graph_constant_time_edge_add_and_remove.html
@@ -0,0 +1,91 @@
+
+
+
+Boost Graph Library: Undirected Graph with constant time edge add and remove
+
+
+
+
+
+
+
+undirected_graph_constant_time_edge_add_and_remove<VertexProp, EdgeProp, GraphProp>
+
+
+
+
+
+The undirected_graph_constant_time_edge_add_and_remove class template is derived from BGL undirected graph. This class is provided only for constant time edge remove, in case that is not needed use undirected graph instead.
+
+
Example
+
+An example of using an undirected_graph_constant_time_edge_add_and_remove is available here libs/graph/example/undirected_graph_constant_time_edge_add and_remove.cpp. It demonstrates that undirected_graph takes quadratic time while undirected_graph_constant_time_edge_and_remove takes only linear time for clearing all outer vertices of wheel graph Wn.
+
+
+
+
+ typedef boost::undirected_graph_constant_time_edge_add_and_remove<
+ boost::no_property, boost::no_property, boost::no_property > Graph;
+ Graph g;
+ typedef typename Graph::vertex_descriptor vertex_descriptor;
+ typedef typename Graph::edge_descriptor edge_descriptor;
+
+ vertex_descriptor v0 = g.add_vertex();
+ vertex_descriptor v1 = g.add_vertex();
+ edge_descriptor e = g.add_edge(v0, v1).first;
+ g.remove_edge(e);
+
+
+Template Parameters
+
+
+
+
+| Parameter | Description | Default |
+
+
+| VertexProp |
+A property map for the graph vertices. |
+ |
+
+
+
+| EdgeProp |
+A property map for the graph edges. |
+ |
+
+
+
+| GraphProp |
+A property map for the graph itself. |
+
+
+
+
+
+
Where Defined
+
+
+boost/graph/undirected_graph_constant_time_edge_add_and_remove.hpp
+
+
+
+
+
+
+
+
+
diff --git a/example/planar_vertex_six_coloring.cpp b/example/planar_vertex_six_coloring.cpp
new file mode 100644
index 000000000..3f7deb514
--- /dev/null
+++ b/example/planar_vertex_six_coloring.cpp
@@ -0,0 +1,90 @@
+//=======================================================================
+// Copyright 2024
+// Author: Hermann Stamm-Wilbrandt
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//=======================================================================
+#include
+#include
+#include
+
+using namespace boost;
+
+// => ../test/planar_vertex_six_coloring.cpp for application to other planar graphs
+//
+template< class graph > void simple_maximal_planar_random_graph(graph& g, int n);
+
+
+// time measurements
+clock_t start_;
+#define _(blk) std::cerr << #blk << " "; start_ = clock(); blk \
+ std::cerr << (clock()-start_)*1.0/CLOCKS_PER_SEC << "s" << std::endl;
+
+
+int main(int argc, char *argv[]) {
+ typedef adjacency_list< listS, vecS, undirectedS > Graph;
+ typedef graph_traits< Graph >::vertices_size_type vertices_size_type;
+ Graph g;
+
+ _(simple_maximal_planar_random_graph(g, argc < 2 ? 333335 : atoi(argv[1]));)
+
+ std::vector< vertices_size_type > color_vec(num_vertices(g));
+ auto color = make_container_vertex_map(color_vec, g);
+
+ std::cout << num_vertices(g) << " vertices" << std::endl;
+ std::cout << num_edges(g) << " egdes" << std::endl;
+
+ _(vertices_size_type num_colors = planar_vertex_six_coloring(g, color);)
+ std::cout << num_colors << " colors" << std::endl;
+
+ BGL_FORALL_EDGES(e, g, Graph)
+ { BOOST_ASSERT(get(color, source(e, g)) != get(color, target(e, g))); }
+
+ std::cout << "vertex coloring verified" << std::endl;
+
+ return 0;
+}
+
+
+/*
+https://www.researchgate.net/publication/360912158_A_simple_linear_time_algorithm_for_embedding_maximal_planar_graphs_1
+
+"simple_maximal_planar_random_graph()" implements only type==3 of chapter 8.
+With type==4 and type==5 added it would be full blown "maximal_planar_random_graph()".
+
+
+ triangular face T[t] transformation, t chosen randomly:
+
+ T[t][0] T[t][0]
+ +--#--+ +--#--+
+ | | | | |
+ | | | | |
+ | | ==> | i |
+ | | | / \ |
+ | | |/ \|
+ #-----# #-----#
+ T[t][1] T[t][2] T[t][1] T[t][2]
+*/
+template< class graph > void simple_maximal_planar_random_graph(graph& g, int n)
+{
+ BOOST_ASSERT(n > 2);
+ g.clear();
+ std::vector< typename graph::vertex_descriptor> V; V.reserve(n);
+ V[0] = add_vertex(g); V[1] = add_vertex(g); V[2] = add_vertex(g);
+ add_edge(V[0], V[1], g); add_edge(V[0], V[2], g); add_edge(V[1], V[2], g);
+ std::vector> T;
+ // start with inside and outside face of complete graph on 3 vertices
+ T.reserve(2*n-4); T.push_back({0, 1, 2}); T.push_back({0, 1, 2});
+ for (int i=3; i < n; ++i)
+ {
+ unsigned t = random() % T.size();
+ V[i] = add_vertex(g);
+ unsigned v;
+ BOOST_FOREACH(v, T[t]) { add_edge(V[v], V[i], g); }
+ T.push_back(T[t]); T.back()[0] = i;
+ T.push_back(T[t]); T.back()[1] = i;
+ T[t][2] = i;
+ }
+}
diff --git a/example/undirected_graph_constant_time_edge_add_and_remove.cpp b/example/undirected_graph_constant_time_edge_add_and_remove.cpp
new file mode 100644
index 000000000..1b93fb02f
--- /dev/null
+++ b/example/undirected_graph_constant_time_edge_add_and_remove.cpp
@@ -0,0 +1,103 @@
+//=======================================================================
+// Copyright 2024
+// Author: Hermann Stamm-Wilbrandt
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//=======================================================================
+#include
+#include
+#include
+#include
+#include
+
+typedef boost::undirected_graph_constant_time_edge_add_and_remove<
+ boost::no_property, boost::no_property, boost::no_property > ugraph_o1;
+
+typedef boost::undirected_graph<
+ boost::no_property, boost::no_property, boost::no_property > ugraph;
+
+
+/*
+ Wheel graphs W5 4 W7 6---1
+ /|\ / \ / \
+ / | \ 5---0---2
+ 3--0--1 \ / \ /
+ \ | / 4---3
+ \|/
+ 2
+*/
+template< class Graph > void wheel(Graph& g, int n);
+
+
+/*
+ Demo function removing the edges for all but central vertex of
+ wheel graph Wn, showing roughly linear time for ugraph_01
+ [because of O(1) remove_edge()] and quadratic time for ugraph.
+
+ Very simplified version of what planar_vertex_six_coloring() does.
+ Proof that boost::undirected_graph_constant_time_edge_add_and_remove
+ class is essential for linear runtime of that vertex coloring algorithm.
+*/
+template< class Graph > float clear_vertices(Graph& g, int n)
+{
+ wheel(g, n);
+
+ std::vector< typename Graph::vertex_descriptor > vec;
+ vec.reserve(num_vertices(g));
+
+ BGL_FORALL_VERTICES_T(v, g, Graph) { vec.push_back(v); }
+
+ clock_t start = clock();
+
+ typename Graph::vertex_descriptor u;
+ BOOST_REVERSE_FOREACH(u, vec) { g.clear_vertex(u); }
+
+ return (clock()-start)*1.0/CLOCKS_PER_SEC;
+}
+
+
+int main(int argc, char*argv[]) {
+ int n = argc < 2 ? 2000 : atoi(argv[1]);
+ ugraph_o1 UO1;
+ ugraph U;
+
+ std::cout << "Wn ugraph_o1 ugraph runtimes [s]" << std::endl;
+
+ for (int i=0; i <= 4; ++i, n*=2)
+ {
+ std::cout << n << " "
+ << clear_vertices(UO1, n) << " "
+ << clear_vertices(U, n) << std::endl;
+ }
+
+ return 0;
+}
+
+
+template< class Graph >
+void wheel(Graph& g, int n)
+{
+ typedef typename Graph::vertex_descriptor vertex_descriptor;
+
+ BOOST_ASSERT(n > 3);
+
+ g = Graph();
+
+ vertex_descriptor v = add_vertex(g);
+ vertex_descriptor w = add_vertex(g);
+ g.add_edge(v, w);
+
+ vertex_descriptor x = w;
+
+ for (int i=3; i <= n; ++i)
+ {
+ vertex_descriptor y = add_vertex(g);
+ g.add_edge(v, y);
+ g.add_edge(x, y);
+ x = y;
+ }
+
+ g.add_edge(x, w);
+}
diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp
index ed5a1d483..f80ed8fba 100644
--- a/include/boost/graph/detail/adjacency_list.hpp
+++ b/include/boost/graph/detail/adjacency_list.hpp
@@ -797,6 +797,32 @@ namespace detail
}
g.m_edges.erase(edge_iter_to_erase);
}
+
+ // O(1)
+ template < class OutEdgeList_iterator, class Config >
+ static void apply(OutEdgeList_iterator iter1,
+ OutEdgeList_iterator iter2,
+ undirected_graph_helper< Config >& g_, StoredProperty&)
+ {
+ typedef typename Config::global_edgelist_selector EdgeListS;
+ BOOST_STATIC_ASSERT((is_same< EdgeListS, listS >::value));
+
+ typedef typename Config::graph_type graph_type;
+ graph_type& g = static_cast< graph_type& >(g_);
+ typename Config::edge_descriptor e = *iter1;
+ typename Config::edge_descriptor f = *iter2;
+ BOOST_ASSERT(source(e, g) == target(f, g));
+ BOOST_ASSERT(source(f, g) == target(e, g));
+
+ typename Config::OutEdgeList& out_el
+ = g.out_edge_list(source(e, g));
+ typename Config::EdgeIter edge_iter_to_erase;
+ edge_iter_to_erase = (*iter1.base()).get_iter();
+ out_el.erase(iter1.base());
+ typename Config::OutEdgeList& in_el = g.out_edge_list(target(e, g));
+ in_el.erase(iter2.base());
+ g.m_edges.erase(edge_iter_to_erase);
+ }
};
template <> struct remove_undirected_edge_dispatch< no_property >
@@ -833,6 +859,32 @@ namespace detail
}
g.m_edges.erase(edge_iter_to_erase);
}
+
+ // O(1)
+ template < class OutEdgeList_iterator, class Config >
+ static void apply(OutEdgeList_iterator iter1,
+ OutEdgeList_iterator iter2,
+ undirected_graph_helper< Config >& g_, no_property&)
+ {
+ typedef typename Config::global_edgelist_selector EdgeListS;
+ BOOST_STATIC_ASSERT((is_same< EdgeListS, listS >::value));
+
+ typedef typename Config::graph_type graph_type;
+ graph_type& g = static_cast< graph_type& >(g_);
+ typename Config::edge_descriptor e = *iter1;
+ typename Config::edge_descriptor f = *iter2;
+ BOOST_ASSERT(source(e, g) == target(f, g));
+ BOOST_ASSERT(source(f, g) == target(e, g));
+
+ typename Config::OutEdgeList& out_el
+ = g.out_edge_list(source(e, g));
+ typename Config::EdgeIter edge_iter_to_erase;
+ edge_iter_to_erase = (*iter1.base()).get_iter();
+ out_el.erase(iter1.base());
+ typename Config::OutEdgeList& in_el = g.out_edge_list(target(e, g));
+ in_el.erase(iter2.base());
+ g.m_edges.erase(edge_iter_to_erase);
+ }
};
// O(E/V)
@@ -924,6 +976,17 @@ template < class Config > struct undirected_graph_helper
{
this->remove_edge(*iter);
}
+ // O(1)
+ inline void remove_edge(typename Config::out_edge_iterator iter1,
+ typename Config::out_edge_iterator iter2)
+ {
+ typedef typename Config::global_edgelist_selector EdgeListS;
+ BOOST_STATIC_ASSERT((!is_same< EdgeListS, vecS >::value));
+
+ typedef typename Config::OutEdgeList::value_type::property_type PType;
+ detail::remove_undirected_edge_dispatch< PType >::apply(
+ iter1, iter2, *this, *(PType*)((*iter1).get_property()));
+ }
};
// Had to make these non-members to avoid accidental instantiation
@@ -953,6 +1016,17 @@ inline void remove_edge(EdgeOrIter e, undirected_graph_helper< Config >& g_)
g_.remove_edge(e);
}
+// O(1)
+template < class OutEdgeIter, class Config >
+inline void remove_edge_(OutEdgeIter i1, OutEdgeIter i2,
+ undirected_graph_helper< Config >& g_)
+{
+ typedef typename Config::global_edgelist_selector EdgeListS;
+ BOOST_STATIC_ASSERT((is_same< EdgeListS, listS >::value));
+
+ g_.remove_edge(i1, i2);
+}
+
// O(E/V) or O(log(E/V))
template < class Config >
void remove_edge(typename Config::vertex_descriptor u,
diff --git a/include/boost/graph/planar_vertex_six_coloring.hpp b/include/boost/graph/planar_vertex_six_coloring.hpp
new file mode 100644
index 000000000..17a374306
--- /dev/null
+++ b/include/boost/graph/planar_vertex_six_coloring.hpp
@@ -0,0 +1,120 @@
+//=======================================================================
+// Copyright 2024
+// Author: Hermann Stamm-Wilbrandt
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//=======================================================================
+//
+#ifndef BOOST_GRAPH_PLANAR_VERTEX_SIX_COLORING_HPP
+#define BOOST_GRAPH_PLANAR_VERTEX_SIX_COLORING_HPP
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* This algorithm is to find a vertex six coloring of a planar graph
+
+ Algorithm:
+ Let G = (V,E) be a planar graph with n vertices.
+ Planar graphs always have a vertex of degree 5 or less.
+ Remember its (at most 5) adjacent vertices and remove its edges.
+ Repeat until all vertices have been processed.
+ Now color the vertices in reverse order they were removed.
+ Assign smallest color different to all <=5 remembered vertices to vertex.
+ Repeat until done.
+
+ The color of the vertex v will be stored in color[v].
+ i.e., vertex v belongs to coloring color[v] */
+
+namespace boost
+{
+ enum vertex_back_t { vertex_back };
+ BOOST_INSTALL_PROPERTY(vertex, back);
+
+template < class VertexListGraph, class ColorMap >
+typename property_traits< ColorMap >::value_type planar_vertex_six_coloring(
+ const VertexListGraph& G, ColorMap color)
+{
+ typedef typename VertexListGraph::vertex_descriptor vertex_descriptor;
+
+ typedef typename property_traits< ColorMap >::value_type size_type;
+
+ typedef undirected_graph_constant_time_edge_add_and_remove<
+ property< vertex_back_t, vertex_descriptor >,
+ no_property, no_property > ugraph_o1;
+
+
+ std::vector< typename ugraph_o1::vertex_descriptor >
+ vertex_u(num_vertices(G));
+ auto vmap = make_container_vertex_map(vertex_u, G);
+//
+// get(vmap, _)
+// {v,w} in V(G)--------------->
+// <---------------V(U) <= {u,t}
+// back[_]
+//
+// Determine copy U of G with linkage
+//
+ ugraph_o1 U;
+
+ auto back = get(vertex_back, U);
+
+
+ BGL_FORALL_VERTICES_T(v, G, VertexListGraph)
+ { put(vmap, v, U.add_vertex(v)); }
+
+ BGL_FORALL_EDGES_T(e, G, VertexListGraph)
+ { U.add_edge(get(vmap, source(e, G)), get(vmap, target(e, G))); }
+
+/*
+ Determine 5-bounded acyclic orientation
+
+ Marek Chrobak, David Eppstein
+ "Planar orientations with low out-degree and compaction of adjacency matrices"
+ Theoretical Computer Science 1991
+ https://dl.acm.org/doi/10.1016/0304-3975%2891%2990020-3
+*/
+ std::vector< typename ugraph_o1::vertex_descriptor > small, visited;
+ std::vector< vertex_descriptor > rev;
+ small.reserve(num_vertices(U));
+ visited.reserve(num_vertices(U));
+ rev.reserve(num_vertices(U));
+
+ BGL_FORALL_VERTICES_T(u, U, ugraph_o1)
+ { if (degree(u, U) <= 5) { small.push_back(u); } }
+
+
+ while (!small.empty())
+ {
+ typename ugraph_o1::vertex_descriptor u = small.back();
+ small.pop_back();
+
+ BGL_FORALL_ADJ_T(u, t, U, ugraph_o1)
+ {
+ if (degree(t, U) == 6) small.push_back(t);
+ }
+ U.clear_vertex(u);
+
+ visited.push_back(u);
+ }
+
+ BOOST_ASSERT(num_vertices(U) == visited.size());
+
+// call sequential_vertex_coloring()
+// with reverse order of 5-bounded acyclic orientation determination
+//
+ BOOST_REVERSE_FOREACH(typename ugraph_o1::vertex_descriptor u, visited)
+ rev.push_back(back[u]);
+
+ return sequential_vertex_coloring(
+ G, make_container_vertex_map(rev, G), color);
+}
+
+} // namespace boost
+
+#endif // BOOST_GRAPH_PLANAR_VERTEX_SIX_COLORING_HPP
diff --git a/include/boost/graph/undirected_graph.hpp b/include/boost/graph/undirected_graph.hpp
index ec1bbbba6..3ec353ef3 100644
--- a/include/boost/graph/undirected_graph.hpp
+++ b/include/boost/graph/undirected_graph.hpp
@@ -340,6 +340,14 @@ class undirected_graph
std::swap(m_max_edge_index, g.m_max_edge_index);
}
+protected:
+ void remove_edge_(void *p)
+ {
+ auto *q = static_cast< std::pair< out_edge_iterator, out_edge_iterator > * >(p);
+ boost::remove_edge_(q->first, q->second, m_graph);
+ --m_num_edges;
+ }
+
private:
vertices_size_type renumber_vertex_indices(
vertex_iterator i, vertex_iterator end, vertices_size_type n)
diff --git a/include/boost/graph/undirected_graph_constant_time_edge_add_and_remove.hpp b/include/boost/graph/undirected_graph_constant_time_edge_add_and_remove.hpp
new file mode 100644
index 000000000..0c32e3a02
--- /dev/null
+++ b/include/boost/graph/undirected_graph_constant_time_edge_add_and_remove.hpp
@@ -0,0 +1,122 @@
+//=======================================================================
+// Copyright 2024
+// Author: Hermann Stamm-Wilbrandt
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//=======================================================================
+
+#ifndef BOOST_GRAPH_UNDIRECTED_GRAPH_CONSTANT_TIME_EDGE_ADD_AND_REMOVE_HPP
+#define BOOST_GRAPH_UNDIRECTED_GRAPH_CONSTANT_TIME_EDGE_ADD_AND_REMOVE_HPP
+
+#include
+#include
+#include
+#include
+
+enum edge_oeip_t
+{
+ edge_oeip
+};
+
+namespace boost
+{
+BOOST_INSTALL_PROPERTY(edge, oeip);
+
+
+/**
+ * The undirected_graph_constant_time_edge_add_and_remove class
+ * extends undirected_graph class template of the BGL.
+ * Its only purpose over undirected_graph is to provide
+ * O(1) time remove_edge() (and add_edge()) functions.
+ */
+#define GRAPH_TYPE \
+ undirected_graph< VP, property< edge_oeip_t, void*, EP >, GP >
+
+template< class VP, class EP, class GP>
+class undirected_graph_constant_time_edge_add_and_remove
+ : public GRAPH_TYPE
+{
+ public:
+ typedef GRAPH_TYPE graph_type;
+
+ typedef typename graph_type::vertices_size_type vertices_size_type;
+ typedef typename graph_type::vertex_descriptor vertex_descriptor;
+ typedef typename graph_type::edge_descriptor edge_descriptor;
+ typedef typename graph_type::out_edge_iterator out_edge_iterator;
+ typedef typename graph_type::edge_iterator edge_iterator;
+
+ public:
+ inline undirected_graph_constant_time_edge_add_and_remove()
+ : graph_type()
+ , m_map(get(edge_oeip, *this))
+ {
+ }
+
+ // would miss necessary linkage between x and created graph
+ inline undirected_graph_constant_time_edge_add_and_remove(
+ graph_type const& x) = delete;
+
+ // would miss necessary linkage between graphs
+ inline undirected_graph_constant_time_edge_add_and_remove(
+ vertices_size_type n, GP const& p = GP()) = delete;
+
+ template < typename EdgeIterator >
+ inline undirected_graph_constant_time_edge_add_and_remove(EdgeIterator f,
+ EdgeIterator l,
+ typename GRAPH_TYPE::vertices_size_type n,
+ typename GRAPH_TYPE::edges_size_type m = 0,
+ GP const& p = GP()) = delete;
+
+ // too slow
+ std::pair< edge_descriptor, bool > add_edge(
+ vertex_descriptor u, vertex_descriptor v, EP const& p) = delete;
+
+ // O(1)
+ inline std::pair< edge_descriptor, bool >
+ add_edge(vertex_descriptor u, vertex_descriptor v)
+ {
+ std::pair< edge_descriptor, bool > et = graph_type::add_edge(u, v);
+ BOOST_ASSERT(et.second);
+
+ storage.push_back(std::make_pair(--out_edges(u, *this).second,
+ --out_edges(v, *this).second));
+ m_map[et.first] = reinterpret_cast(&storage.back());
+ return et;
+ }
+
+ // too slow
+ void remove_edge(vertex_descriptor u, vertex_descriptor v) = delete;
+
+ // O(1)
+ void remove_edge(edge_iterator i) { remove_edge(*i); }
+
+ // O(1)
+ inline void remove_edge(edge_descriptor e)
+ {
+ graph_type::remove_edge_(m_map[e]);
+ }
+
+ // O(degree(v))
+ inline void clear_vertex(vertex_descriptor v)
+ {
+ while (true)
+ {
+ out_edge_iterator ei, ei_end;
+ boost::tie(ei, ei_end) = out_edges(v, *this);
+ if (ei == ei_end)
+ break;
+ this->remove_edge(*ei);
+ }
+ }
+
+ private:
+ typename property_map< graph_type, edge_oeip_t >::type m_map;
+ std::list< std::pair< out_edge_iterator, out_edge_iterator > > storage;
+};
+
+} /* namespace boost */
+
+
+#endif
diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
index b2656eb07..0e065d677 100644
--- a/test/Jamfile.v2
+++ b/test/Jamfile.v2
@@ -84,7 +84,8 @@ alias graph_test_regular :
[ compile reverse_graph_cc.cpp ]
[ run sequential_vertex_coloring.cpp ]
-
+ [ run planar_vertex_six_coloring.cpp ]
+
# TODO: Merge these into a single test framework.
[ run subgraph.cpp ]
[ run subgraph_bundled.cpp ]
diff --git a/test/planar_input_graphs/maximal_planar_1000.leda b/test/planar_input_graphs/maximal_planar_1000.leda
new file mode 100644
index 000000000..b0e046119
--- /dev/null
+++ b/test/planar_input_graphs/maximal_planar_1000.leda
@@ -0,0 +1,3999 @@
+LEDA.GRAPH // randomgraph 1000 -t maximal_planar -o maximal_planar_1000.leda
+point
+int
+1000
+(50.00,90.00)
+(50.25,90.00)
+(50.50,90.00)
+(50.75,89.99)
+(51.01,89.99)
+(51.26,89.98)
+(51.51,89.97)
+(51.76,89.96)
+(52.01,89.95)
+(52.26,89.94)
+(52.51,89.92)
+(52.76,89.90)
+(53.01,89.89)
+(53.27,89.87)
+(53.52,89.85)
+(53.77,89.82)
+(54.02,89.80)
+(54.27,89.77)
+(54.52,89.74)
+(54.77,89.72)
+(55.02,89.68)
+(55.26,89.65)
+(55.51,89.62)
+(55.76,89.58)
+(56.01,89.55)
+(56.26,89.51)
+(56.51,89.47)
+(56.76,89.43)
+(57.00,89.38)
+(57.25,89.34)
+(57.50,89.29)
+(57.75,89.24)
+(57.99,89.19)
+(58.24,89.14)
+(58.48,89.09)
+(58.73,89.04)
+(58.97,88.98)
+(59.22,88.92)
+(59.46,88.86)
+(59.71,88.80)
+(59.95,88.74)
+(60.20,88.68)
+(60.44,88.61)
+(60.68,88.55)
+(60.92,88.48)
+(61.16,88.41)
+(61.41,88.34)
+(61.65,88.27)
+(61.89,88.19)
+(62.13,88.12)
+(62.37,88.04)
+(62.60,87.96)
+(62.84,87.88)
+(63.08,87.80)
+(63.32,87.72)
+(63.56,87.63)
+(63.79,87.55)
+(64.03,87.46)
+(64.26,87.37)
+(64.50,87.28)
+(64.73,87.19)
+(64.96,87.10)
+(65.20,87.00)
+(65.43,86.90)
+(65.66,86.81)
+(65.89,86.71)
+(66.12,86.61)
+(66.35,86.50)
+(66.58,86.40)
+(66.81,86.30)
+(67.04,86.19)
+(67.27,86.08)
+(67.49,85.97)
+(67.72,85.86)
+(67.94,85.75)
+(68.17,85.64)
+(68.39,85.52)
+(68.61,85.41)
+(68.84,85.29)
+(69.06,85.17)
+(69.28,85.05)
+(69.50,84.93)
+(69.72,84.80)
+(69.94,84.68)
+(70.15,84.55)
+(70.37,84.42)
+(70.59,84.30)
+(70.80,84.17)
+(71.02,84.03)
+(71.23,83.90)
+(71.44,83.77)
+(71.65,83.63)
+(71.86,83.50)
+(72.07,83.36)
+(72.28,83.22)
+(72.49,83.08)
+(72.70,82.94)
+(72.91,82.79)
+(73.11,82.65)
+(73.32,82.50)
+(73.52,82.35)
+(73.72,82.21)
+(73.93,82.06)
+(74.13,81.90)
+(74.33,81.75)
+(74.53,81.60)
+(74.72,81.44)
+(74.92,81.29)
+(75.12,81.13)
+(75.31,80.97)
+(75.51,80.81)
+(75.70,80.65)
+(75.89,80.49)
+(76.08,80.33)
+(76.27,80.16)
+(76.46,80.00)
+(76.65,79.83)
+(76.84,79.66)
+(77.02,79.49)
+(77.21,79.32)
+(77.39,79.15)
+(77.57,78.98)
+(77.76,78.80)
+(77.94,78.63)
+(78.12,78.45)
+(78.29,78.27)
+(78.47,78.10)
+(78.65,77.92)
+(78.82,77.74)
+(79.00,77.55)
+(79.17,77.37)
+(79.34,77.19)
+(79.51,77.00)
+(79.68,76.82)
+(79.85,76.63)
+(80.01,76.44)
+(80.18,76.25)
+(80.34,76.06)
+(80.51,75.87)
+(80.67,75.68)
+(80.83,75.48)
+(80.99,75.29)
+(81.15,75.10)
+(81.31,74.90)
+(81.46,74.70)
+(81.62,74.50)
+(81.77,74.30)
+(81.92,74.10)
+(82.07,73.90)
+(82.22,73.70)
+(82.37,73.50)
+(82.52,73.29)
+(82.66,73.09)
+(82.81,72.88)
+(82.95,72.68)
+(83.09,72.47)
+(83.23,72.26)
+(83.37,72.05)
+(83.51,71.84)
+(83.65,71.63)
+(83.78,71.42)
+(83.92,71.21)
+(84.05,70.99)
+(84.18,70.78)
+(84.31,70.56)
+(84.44,70.35)
+(84.57,70.13)
+(84.69,69.91)
+(84.82,69.69)
+(84.94,69.47)
+(85.06,69.25)
+(85.18,69.03)
+(85.30,68.81)
+(85.42,68.59)
+(85.53,68.37)
+(85.65,68.14)
+(85.76,67.92)
+(85.87,67.69)
+(85.98,67.47)
+(86.09,67.24)
+(86.20,67.01)
+(86.31,66.78)
+(86.41,66.56)
+(86.52,66.33)
+(86.62,66.10)
+(86.72,65.87)
+(86.82,65.64)
+(86.92,65.40)
+(87.01,65.17)
+(87.11,64.94)
+(87.20,64.71)
+(87.29,64.47)
+(87.38,64.24)
+(87.47,64.00)
+(87.56,63.77)
+(87.64,63.53)
+(87.73,63.29)
+(87.81,63.05)
+(87.89,62.82)
+(87.97,62.58)
+(88.05,62.34)
+(88.13,62.10)
+(88.20,61.86)
+(88.28,61.62)
+(88.35,61.38)
+(88.42,61.14)
+(88.49,60.90)
+(88.56,60.65)
+(88.62,60.41)
+(88.69,60.17)
+(88.75,59.92)
+(88.81,59.68)
+(88.87,59.44)
+(88.93,59.19)
+(88.99,58.95)
+(89.04,58.70)
+(89.10,58.46)
+(89.15,58.21)
+(89.20,57.96)
+(89.25,57.72)
+(89.30,57.47)
+(89.34,57.22)
+(89.39,56.98)
+(89.43,56.73)
+(89.47,56.48)
+(89.51,56.23)
+(89.55,55.98)
+(89.59,55.74)
+(89.62,55.49)
+(89.66,55.24)
+(89.69,54.99)
+(89.72,54.74)
+(89.75,54.49)
+(89.77,54.24)
+(89.80,53.99)
+(89.82,53.74)
+(89.85,53.49)
+(89.87,53.24)
+(89.89,52.99)
+(89.91,52.74)
+(89.92,52.48)
+(89.94,52.23)
+(89.95,51.98)
+(89.96,51.73)
+(89.97,51.48)
+(89.98,51.23)
+(89.99,50.98)
+(89.99,50.73)
+(90.00,50.47)
+(90.00,50.22)
+(90.00,49.97)
+(90.00,49.72)
+(90.00,49.47)
+(89.99,49.22)
+(89.99,48.97)
+(89.98,48.71)
+(89.97,48.46)
+(89.96,48.21)
+(89.95,47.96)
+(89.93,47.71)
+(89.92,47.46)
+(89.90,47.21)
+(89.88,46.96)
+(89.86,46.71)
+(89.84,46.46)
+(89.82,46.21)
+(89.80,45.96)
+(89.77,45.71)
+(89.74,45.46)
+(89.71,45.21)
+(89.68,44.96)
+(89.65,44.71)
+(89.61,44.46)
+(89.58,44.21)
+(89.54,43.96)
+(89.50,43.71)
+(89.46,43.46)
+(89.42,43.22)
+(89.38,42.97)
+(89.33,42.72)
+(89.29,42.47)
+(89.24,42.23)
+(89.19,41.98)
+(89.14,41.73)
+(89.08,41.49)
+(89.03,41.24)
+(88.97,41.00)
+(88.92,40.75)
+(88.86,40.51)
+(88.80,40.26)
+(88.74,40.02)
+(88.67,39.78)
+(88.61,39.53)
+(88.54,39.29)
+(88.47,39.05)
+(88.40,38.81)
+(88.33,38.57)
+(88.26,38.33)
+(88.18,38.09)
+(88.11,37.85)
+(88.03,37.61)
+(87.95,37.37)
+(87.87,37.13)
+(87.79,36.89)
+(87.71,36.65)
+(87.62,36.42)
+(87.54,36.18)
+(87.45,35.95)
+(87.36,35.71)
+(87.27,35.48)
+(87.18,35.24)
+(87.08,35.01)
+(86.99,34.78)
+(86.89,34.54)
+(86.80,34.31)
+(86.70,34.08)
+(86.60,33.85)
+(86.49,33.62)
+(86.39,33.39)
+(86.28,33.16)
+(86.18,32.94)
+(86.07,32.71)
+(85.96,32.48)
+(85.85,32.26)
+(85.74,32.03)
+(85.62,31.81)
+(85.51,31.58)
+(85.39,31.36)
+(85.27,31.14)
+(85.15,30.92)
+(85.03,30.70)
+(84.91,30.48)
+(84.79,30.26)
+(84.66,30.04)
+(84.54,29.82)
+(84.41,29.61)
+(84.28,29.39)
+(84.15,29.17)
+(84.02,28.96)
+(83.89,28.75)
+(83.75,28.53)
+(83.62,28.32)
+(83.48,28.11)
+(83.34,27.90)
+(83.20,27.69)
+(83.06,27.48)
+(82.92,27.28)
+(82.78,27.07)
+(82.63,26.87)
+(82.48,26.66)
+(82.34,26.46)
+(82.19,26.25)
+(82.04,26.05)
+(81.89,25.85)
+(81.74,25.65)
+(81.58,25.45)
+(81.43,25.25)
+(81.27,25.06)
+(81.11,24.86)
+(80.95,24.67)
+(80.79,24.47)
+(80.63,24.28)
+(80.47,24.09)
+(80.31,23.90)
+(80.14,23.71)
+(79.98,23.52)
+(79.81,23.33)
+(79.64,23.14)
+(79.47,22.96)
+(79.30,22.77)
+(79.13,22.59)
+(78.96,22.41)
+(78.78,22.22)
+(78.61,22.04)
+(78.43,21.86)
+(78.25,21.69)
+(78.08,21.51)
+(77.90,21.33)
+(77.72,21.16)
+(77.53,20.98)
+(77.35,20.81)
+(77.17,20.64)
+(76.98,20.47)
+(76.80,20.30)
+(76.61,20.13)
+(76.42,19.97)
+(76.23,19.80)
+(76.04,19.64)
+(75.85,19.47)
+(75.66,19.31)
+(75.46,19.15)
+(75.27,18.99)
+(75.07,18.83)
+(74.88,18.68)
+(74.68,18.52)
+(74.48,18.37)
+(74.28,18.21)
+(74.08,18.06)
+(73.88,17.91)
+(73.68,17.76)
+(73.47,17.61)
+(73.27,17.47)
+(73.07,17.32)
+(72.86,17.18)
+(72.65,17.03)
+(72.45,16.89)
+(72.24,16.75)
+(72.03,16.61)
+(71.82,16.47)
+(71.61,16.34)
+(71.39,16.20)
+(71.18,16.07)
+(70.97,15.94)
+(70.75,15.80)
+(70.54,15.67)
+(70.32,15.55)
+(70.10,15.42)
+(69.89,15.29)
+(69.67,15.17)
+(69.45,15.05)
+(69.23,14.92)
+(69.01,14.80)
+(68.79,14.69)
+(68.56,14.57)
+(68.34,14.45)
+(68.12,14.34)
+(67.89,14.22)
+(67.67,14.11)
+(67.44,14.00)
+(67.21,13.89)
+(66.99,13.79)
+(66.76,13.68)
+(66.53,13.58)
+(66.30,13.47)
+(66.07,13.37)
+(65.84,13.27)
+(65.61,13.17)
+(65.38,13.07)
+(65.15,12.98)
+(64.91,12.88)
+(64.68,12.79)
+(64.44,12.70)
+(64.21,12.61)
+(63.97,12.52)
+(63.74,12.43)
+(63.50,12.35)
+(63.27,12.26)
+(63.03,12.18)
+(62.79,12.10)
+(62.55,12.02)
+(62.31,11.94)
+(62.07,11.87)
+(61.83,11.79)
+(61.59,11.72)
+(61.35,11.64)
+(61.11,11.57)
+(60.87,11.50)
+(60.63,11.44)
+(60.38,11.37)
+(60.14,11.31)
+(59.90,11.24)
+(59.65,11.18)
+(59.41,11.12)
+(59.16,11.06)
+(58.92,11.01)
+(58.67,10.95)
+(58.43,10.90)
+(58.18,10.85)
+(57.94,10.80)
+(57.69,10.75)
+(57.44,10.70)
+(57.20,10.65)
+(56.95,10.61)
+(56.70,10.57)
+(56.45,10.52)
+(56.20,10.48)
+(55.96,10.45)
+(55.71,10.41)
+(55.46,10.37)
+(55.21,10.34)
+(54.96,10.31)
+(54.71,10.28)
+(54.46,10.25)
+(54.21,10.22)
+(53.96,10.20)
+(53.71,10.17)
+(53.46,10.15)
+(53.21,10.13)
+(52.96,10.11)
+(52.71,10.09)
+(52.46,10.08)
+(52.21,10.06)
+(51.95,10.05)
+(51.70,10.04)
+(51.45,10.03)
+(51.20,10.02)
+(50.95,10.01)
+(50.70,10.01)
+(50.45,10.00)
+(50.20,10.00)
+(49.94,10.00)
+(49.69,10.00)
+(49.44,10.00)
+(49.19,10.01)
+(48.94,10.01)
+(48.69,10.02)
+(48.44,10.03)
+(48.18,10.04)
+(47.93,10.05)
+(47.68,10.07)
+(47.43,10.08)
+(47.18,10.10)
+(46.93,10.12)
+(46.68,10.14)
+(46.43,10.16)
+(46.18,10.18)
+(45.93,10.21)
+(45.68,10.23)
+(45.43,10.26)
+(45.18,10.29)
+(44.93,10.32)
+(44.68,10.36)
+(44.43,10.39)
+(44.18,10.43)
+(43.93,10.46)
+(43.68,10.50)
+(43.44,10.54)
+(43.19,10.58)
+(42.94,10.63)
+(42.69,10.67)
+(42.45,10.72)
+(42.20,10.77)
+(41.95,10.82)
+(41.71,10.87)
+(41.46,10.92)
+(41.22,10.98)
+(40.97,11.03)
+(40.73,11.09)
+(40.48,11.15)
+(40.24,11.21)
+(39.99,11.27)
+(39.75,11.34)
+(39.51,11.40)
+(39.27,11.47)
+(39.02,11.54)
+(38.78,11.61)
+(38.54,11.68)
+(38.30,11.75)
+(38.06,11.82)
+(37.82,11.90)
+(37.58,11.98)
+(37.34,12.06)
+(37.10,12.14)
+(36.87,12.22)
+(36.63,12.30)
+(36.39,12.39)
+(36.16,12.47)
+(35.92,12.56)
+(35.68,12.65)
+(35.45,12.74)
+(35.22,12.83)
+(34.98,12.93)
+(34.75,13.02)
+(34.52,13.12)
+(34.29,13.22)
+(34.06,13.32)
+(33.83,13.42)
+(33.60,13.52)
+(33.37,13.62)
+(33.14,13.73)
+(32.91,13.83)
+(32.68,13.94)
+(32.46,14.05)
+(32.23,14.16)
+(32.01,14.28)
+(31.78,14.39)
+(31.56,14.50)
+(31.34,14.62)
+(31.11,14.74)
+(30.89,14.86)
+(30.67,14.98)
+(30.45,15.10)
+(30.23,15.22)
+(30.02,15.35)
+(29.80,15.48)
+(29.58,15.60)
+(29.37,15.73)
+(29.15,15.86)
+(28.94,16.00)
+(28.72,16.13)
+(28.51,16.26)
+(28.30,16.40)
+(28.09,16.54)
+(27.88,16.67)
+(27.67,16.81)
+(27.46,16.95)
+(27.25,17.10)
+(27.05,17.24)
+(26.84,17.39)
+(26.64,17.53)
+(26.43,17.68)
+(26.23,17.83)
+(26.03,17.98)
+(25.83,18.13)
+(25.63,18.28)
+(25.43,18.44)
+(25.23,18.59)
+(25.04,18.75)
+(24.84,18.90)
+(24.64,19.06)
+(24.45,19.22)
+(24.26,19.38)
+(24.07,19.55)
+(23.87,19.71)
+(23.68,19.88)
+(23.50,20.04)
+(23.31,20.21)
+(23.12,20.38)
+(22.94,20.55)
+(22.75,20.72)
+(22.57,20.89)
+(22.38,21.06)
+(22.20,21.24)
+(22.02,21.41)
+(21.84,21.59)
+(21.67,21.77)
+(21.49,21.94)
+(21.31,22.12)
+(21.14,22.30)
+(20.97,22.49)
+(20.79,22.67)
+(20.62,22.85)
+(20.45,23.04)
+(20.28,23.23)
+(20.11,23.41)
+(19.95,23.60)
+(19.78,23.79)
+(19.62,23.98)
+(19.46,24.17)
+(19.29,24.37)
+(19.13,24.56)
+(18.97,24.75)
+(18.82,24.95)
+(18.66,25.15)
+(18.50,25.34)
+(18.35,25.54)
+(18.20,25.74)
+(18.04,25.94)
+(17.89,26.14)
+(17.74,26.34)
+(17.60,26.55)
+(17.45,26.75)
+(17.30,26.96)
+(17.16,27.16)
+(17.02,27.37)
+(16.88,27.58)
+(16.74,27.79)
+(16.60,28.00)
+(16.46,28.21)
+(16.32,28.42)
+(16.19,28.63)
+(16.05,28.84)
+(15.92,29.06)
+(15.79,29.27)
+(15.66,29.49)
+(15.53,29.70)
+(15.41,29.92)
+(15.28,30.14)
+(15.16,30.36)
+(15.03,30.58)
+(14.91,30.80)
+(14.79,31.02)
+(14.67,31.24)
+(14.56,31.46)
+(14.44,31.68)
+(14.33,31.91)
+(14.21,32.13)
+(14.10,32.36)
+(13.99,32.58)
+(13.88,32.81)
+(13.77,33.04)
+(13.67,33.27)
+(13.56,33.49)
+(13.46,33.72)
+(13.36,33.95)
+(13.26,34.18)
+(13.16,34.42)
+(13.06,34.65)
+(12.97,34.88)
+(12.87,35.11)
+(12.78,35.35)
+(12.69,35.58)
+(12.60,35.82)
+(12.51,36.05)
+(12.42,36.29)
+(12.34,36.52)
+(12.25,36.76)
+(12.17,37.00)
+(12.09,37.24)
+(12.01,37.48)
+(11.93,37.71)
+(11.86,37.95)
+(11.78,38.19)
+(11.71,38.43)
+(11.64,38.68)
+(11.57,38.92)
+(11.50,39.16)
+(11.43,39.40)
+(11.36,39.64)
+(11.30,39.89)
+(11.24,40.13)
+(11.18,40.37)
+(11.12,40.62)
+(11.06,40.86)
+(11.00,41.11)
+(10.95,41.35)
+(10.89,41.60)
+(10.84,41.84)
+(10.79,42.09)
+(10.74,42.34)
+(10.69,42.58)
+(10.65,42.83)
+(10.60,43.08)
+(10.56,43.33)
+(10.52,43.57)
+(10.48,43.82)
+(10.44,44.07)
+(10.41,44.32)
+(10.37,44.57)
+(10.34,44.82)
+(10.31,45.07)
+(10.27,45.32)
+(10.25,45.57)
+(10.22,45.82)
+(10.19,46.07)
+(10.17,46.32)
+(10.15,46.57)
+(10.13,46.82)
+(10.11,47.07)
+(10.09,47.32)
+(10.07,47.57)
+(10.06,47.82)
+(10.05,48.07)
+(10.04,48.32)
+(10.03,48.58)
+(10.02,48.83)
+(10.01,49.08)
+(10.01,49.33)
+(10.00,49.58)
+(10.00,49.83)
+(10.00,50.08)
+(10.00,50.34)
+(10.00,50.59)
+(10.01,50.84)
+(10.01,51.09)
+(10.02,51.34)
+(10.03,51.59)
+(10.04,51.84)
+(10.05,52.10)
+(10.07,52.35)
+(10.08,52.60)
+(10.10,52.85)
+(10.12,53.10)
+(10.14,53.35)
+(10.16,53.60)
+(10.19,53.85)
+(10.21,54.10)
+(10.24,54.35)
+(10.27,54.60)
+(10.30,54.85)
+(10.33,55.10)
+(10.36,55.35)
+(10.39,55.60)
+(10.43,55.85)
+(10.47,56.10)
+(10.51,56.34)
+(10.55,56.59)
+(10.59,56.84)
+(10.63,57.09)
+(10.68,57.33)
+(10.73,57.58)
+(10.77,57.83)
+(10.82,58.07)
+(10.88,58.32)
+(10.93,58.57)
+(10.98,58.81)
+(11.04,59.06)
+(11.10,59.30)
+(11.16,59.55)
+(11.22,59.79)
+(11.28,60.03)
+(11.34,60.28)
+(11.41,60.52)
+(11.47,60.76)
+(11.54,61.00)
+(11.61,61.25)
+(11.68,61.49)
+(11.76,61.73)
+(11.83,61.97)
+(11.91,62.21)
+(11.99,62.45)
+(12.06,62.69)
+(12.15,62.92)
+(12.23,63.16)
+(12.31,63.40)
+(12.40,63.63)
+(12.48,63.87)
+(12.57,64.11)
+(12.66,64.34)
+(12.75,64.58)
+(12.84,64.81)
+(12.94,65.04)
+(13.03,65.28)
+(13.13,65.51)
+(13.23,65.74)
+(13.33,65.97)
+(13.43,66.20)
+(13.53,66.43)
+(13.63,66.66)
+(13.74,66.89)
+(13.85,67.11)
+(13.95,67.34)
+(14.06,67.57)
+(14.18,67.79)
+(14.29,68.02)
+(14.40,68.24)
+(14.52,68.47)
+(14.63,68.69)
+(14.75,68.91)
+(14.87,69.13)
+(14.99,69.35)
+(15.12,69.57)
+(15.24,69.79)
+(15.36,70.01)
+(15.49,70.23)
+(15.62,70.44)
+(15.75,70.66)
+(15.88,70.87)
+(16.01,71.09)
+(16.14,71.30)
+(16.28,71.51)
+(16.41,71.72)
+(16.55,71.94)
+(16.69,72.14)
+(16.83,72.35)
+(16.97,72.56)
+(17.11,72.77)
+(17.26,72.98)
+(17.40,73.18)
+(17.55,73.39)
+(17.70,73.59)
+(17.84,73.79)
+(17.99,73.99)
+(18.15,74.19)
+(18.30,74.39)
+(18.45,74.59)
+(18.61,74.79)
+(18.76,74.99)
+(18.92,75.18)
+(19.08,75.38)
+(19.24,75.57)
+(19.40,75.76)
+(19.57,75.96)
+(19.73,76.15)
+(19.89,76.34)
+(20.06,76.53)
+(20.23,76.71)
+(20.40,76.90)
+(20.57,77.09)
+(20.74,77.27)
+(20.91,77.45)
+(21.08,77.64)
+(21.26,77.82)
+(21.43,78.00)
+(21.61,78.18)
+(21.79,78.35)
+(21.96,78.53)
+(22.14,78.71)
+(22.33,78.88)
+(22.51,79.05)
+(22.69,79.23)
+(22.87,79.40)
+(23.06,79.57)
+(23.25,79.74)
+(23.43,79.90)
+(23.62,80.07)
+(23.81,80.24)
+(24.00,80.40)
+(24.19,80.56)
+(24.39,80.72)
+(24.58,80.88)
+(24.77,81.04)
+(24.97,81.20)
+(25.17,81.36)
+(25.36,81.51)
+(25.56,81.67)
+(25.76,81.82)
+(25.96,81.97)
+(26.16,82.12)
+(26.37,82.27)
+(26.57,82.42)
+(26.77,82.57)
+(26.98,82.71)
+(27.19,82.86)
+(27.39,83.00)
+(27.60,83.14)
+(27.81,83.28)
+(28.02,83.42)
+(28.23,83.56)
+(28.44,83.69)
+(28.65,83.83)
+(28.87,83.96)
+(29.08,84.09)
+(29.30,84.22)
+(29.51,84.35)
+(29.73,84.48)
+(29.94,84.61)
+(30.16,84.73)
+(30.38,84.86)
+(30.60,84.98)
+(30.82,85.10)
+(31.04,85.22)
+(31.26,85.34)
+(31.49,85.46)
+(31.71,85.57)
+(31.93,85.69)
+(32.16,85.80)
+(32.38,85.91)
+(32.61,86.02)
+(32.84,86.13)
+(33.06,86.24)
+(33.29,86.34)
+(33.52,86.45)
+(33.75,86.55)
+(33.98,86.65)
+(34.21,86.75)
+(34.44,86.85)
+(34.67,86.95)
+(34.91,87.04)
+(35.14,87.14)
+(35.37,87.23)
+(35.61,87.32)
+(35.84,87.41)
+(36.08,87.50)
+(36.31,87.59)
+(36.55,87.67)
+(36.79,87.75)
+(37.03,87.84)
+(37.26,87.92)
+(37.50,88.00)
+(37.74,88.08)
+(37.98,88.15)
+(38.22,88.23)
+(38.46,88.30)
+(38.70,88.37)
+(38.94,88.44)
+(39.19,88.51)
+(39.43,88.58)
+(39.67,88.64)
+(39.91,88.71)
+(40.16,88.77)
+(40.40,88.83)
+(40.65,88.89)
+(40.89,88.95)
+(41.13,89.01)
+(41.38,89.06)
+(41.63,89.11)
+(41.87,89.17)
+(42.12,89.22)
+(42.37,89.26)
+(42.61,89.31)
+(42.86,89.36)
+(43.11,89.40)
+(43.35,89.44)
+(43.60,89.49)
+(43.85,89.52)
+(44.10,89.56)
+(44.35,89.60)
+(44.60,89.63)
+(44.85,89.67)
+(45.10,89.70)
+(45.35,89.73)
+(45.60,89.76)
+(45.85,89.78)
+(46.10,89.81)
+(46.35,89.83)
+(46.60,89.85)
+(46.85,89.88)
+(47.10,89.89)
+(47.35,89.91)
+(47.60,89.93)
+(47.85,89.94)
+(48.10,89.95)
+(48.35,89.97)
+(48.60,89.98)
+(48.86,89.98)
+(49.11,89.99)
+(49.36,89.99)
+(49.61,90.00)
+(49.86,90.00)
+2994
+8 3 0
+9 8 0
+10 6 0
+13 3 0
+15 6 0
+15 7 0
+15 5 0
+16 1 0
+17 7 0
+19 8 0
+19 18 0
+20 4 0
+20 2 0
+21 5 0
+22 5 0
+25 10 0
+25 24 0
+27 10 0
+27 20 0
+27 25 0
+28 12 0
+29 11 0
+29 23 0
+30 4 0
+30 20 0
+33 13 0
+33 32 0
+34 2 0
+36 17 0
+37 13 0
+39 19 0
+39 18 0
+40 33 0
+40 29 0
+41 36 0
+42 8 0
+42 5 0
+44 21 0
+45 18 0
+45 11 0
+46 34 0
+46 20 0
+47 19 0
+48 28 0
+49 5 0
+49 17 0
+50 23 0
+50 18 0
+51 43 0
+52 17 0
+52 38 0
+53 20 0
+53 27 0
+55 3 0
+55 47 0
+57 20 0
+58 3 0
+59 30 0
+59 54 0
+59 56 0
+60 26 0
+60 15 0
+60 7 0
+60 5 0
+61 59 0
+62 12 0
+63 16 0
+63 8 0
+64 29 0
+64 42 0
+65 33 0
+67 7 0
+68 17 0
+68 49 0
+69 7 0
+69 62 0
+69 12 0
+69 28 0
+70 44 0
+71 51 0
+71 9 0
+73 66 0
+73 42 0
+73 64 0
+74 55 0
+75 16 0
+75 1 0
+75 51 0
+76 29 0
+76 41 0
+77 12 0
+77 62 0
+78 59 0
+79 52 0
+79 60 0
+80 50 0
+80 23 0
+80 29 0
+80 11 0
+81 18 0
+81 19 0
+82 57 0
+83 39 0
+83 28 0
+84 7 0
+84 17 0
+85 78 0
+85 59 0
+86 52 0
+87 30 0
+88 35 0
+88 7 0
+88 6 0
+89 47 0
+89 74 0
+89 37 0
+90 29 0
+90 64 0
+90 42 0
+91 8 0
+92 57 0
+93 69 0
+93 88 0
+94 7 0
+96 82 0
+96 22 0
+96 5 0
+97 88 0
+97 6 0
+97 35 0
+98 39 0
+98 83 0
+99 19 0
+100 29 0
+101 41 0
+101 36 0
+101 7 0
+102 72 0
+103 99 0
+103 12 0
+103 19 0
+104 24 0
+104 25 0
+106 35 0
+107 15 0
+108 13 0
+108 32 0
+110 34 0
+110 6 0
+110 10 0
+111 47 0
+111 19 0
+111 8 0
+111 3 0
+112 5 0
+112 52 0
+112 49 0
+113 8 0
+114 31 0
+114 12 0
+115 18 0
+116 34 0
+116 35 0
+118 14 0
+118 39 0
+118 98 0
+119 11 0
+119 7 0
+120 42 0
+120 73 0
+121 37 0
+121 89 0
+121 74 0
+121 109 0
+122 117 0
+123 56 0
+123 59 0
+124 11 0
+124 101 0
+126 8 0
+127 49 0
+127 29 0
+128 101 0
+128 7 0
+129 16 0
+129 114 0
+129 12 0
+130 25 0
+130 24 0
+131 119 0
+132 73 0
+132 66 0
+134 23 0
+134 13 0
+135 11 0
+135 119 0
+136 52 0
+136 84 0
+137 55 0
+137 74 0
+137 89 0
+138 18 0
+139 54 0
+139 10 0
+139 133 0
+139 61 0
+140 73 0
+140 66 0
+141 8 0
+141 63 0
+141 75 0
+142 98 0
+142 39 0
+143 101 0
+143 124 0
+143 11 0
+143 41 0
+144 58 0
+145 40 0
+145 65 0
+145 33 0
+147 11 0
+147 29 0
+147 41 0
+148 5 0
+148 60 0
+148 79 0
+149 32 0
+149 146 0
+149 29 0
+150 29 0
+150 3 0
+151 45 0
+152 9 0
+152 44 0
+153 35 0
+153 116 0
+153 34 0
+154 43 0
+155 112 0
+155 52 0
+157 69 0
+157 28 0
+158 17 0
+158 36 0
+160 1 0
+160 43 0
+161 90 0
+161 5 0
+161 29 0
+162 1 0
+162 16 0
+162 2 0
+162 92 0
+162 160 0
+163 147 0
+163 41 0
+163 143 0
+164 51 0
+165 113 0
+165 91 0
+166 8 0
+166 42 0
+166 120 0
+166 132 0
+167 122 0
+167 72 0
+167 102 0
+167 95 0
+168 17 0
+168 7 0
+168 101 0
+169 117 0
+169 156 0
+169 56 0
+169 102 0
+169 72 0
+170 82 0
+170 4 0
+171 158 0
+171 29 0
+173 130 0
+174 162 0
+174 92 0
+175 11 0
+175 135 0
+175 45 0
+176 69 0
+177 105 0
+178 125 0
+179 55 0
+179 3 0
+180 137 0
+180 89 0
+180 47 0
+181 106 0
+181 97 0
+182 35 0
+182 62 0
+183 4 0
+183 22 0
+183 170 0
+184 2 0
+184 16 0
+184 12 0
+185 139 0
+186 12 0
+187 35 0
+187 182 0
+187 62 0
+188 184 0
+188 129 0
+189 182 0
+189 2 0
+190 170 0
+190 82 0
+190 57 0
+191 59 0
+191 139 0
+191 185 0
+191 61 0
+192 103 0
+192 12 0
+192 114 0
+192 91 0
+193 140 0
+193 66 0
+193 132 0
+193 73 0
+194 30 0
+194 87 0
+195 117 0
+195 122 0
+196 35 0
+196 116 0
+196 153 0
+197 21 0
+197 44 0
+198 10 0
+198 6 0
+199 29 0
+200 71 0
+200 164 0
+200 51 0
+201 18 0
+201 19 0
+201 81 0
+202 5 0
+202 42 0
+203 137 0
+204 110 0
+204 173 0
+204 34 0
+205 16 0
+205 63 0
+206 47 0
+206 111 0
+206 3 0
+206 58 0
+206 55 0
+207 29 0
+208 65 0
+209 54 0
+209 59 0
+210 12 0
+211 29 0
+211 127 0
+212 5 0
+212 148 0
+212 86 0
+212 52 0
+213 96 0
+214 163 0
+214 147 0
+215 80 0
+216 183 0
+216 22 0
+216 170 0
+217 125 0
+218 79 0
+218 52 0
+219 217 0
+219 167 0
+220 133 0
+220 139 0
+220 10 0
+220 4 0
+221 110 0
+221 10 0
+222 207 0
+222 127 0
+222 29 0
+223 173 0
+223 25 0
+223 130 0
+224 59 0
+224 78 0
+224 178 0
+224 123 0
+225 3 0
+225 150 0
+226 100 0
+226 23 0
+226 134 0
+226 145 0
+227 142 0
+227 39 0
+227 177 0
+228 54 0
+228 209 0
+229 114 0
+229 31 0
+230 114 0
+231 3 0
+231 37 0
+231 121 0
+231 109 0
+231 179 0
+232 39 0
+232 118 0
+232 159 0
+233 106 0
+233 35 0
+233 97 0
+233 181 0
+234 8 0
+234 230 0
+235 1 0
+235 160 0
+235 75 0
+236 13 0
+236 23 0
+236 50 0
+236 37 0
+237 95 0
+238 235 0
+239 43 0
+239 51 0
+240 19 0
+240 83 0
+240 28 0
+241 72 0
+241 117 0
+242 70 0
+243 7 0
+244 68 0
+244 17 0
+245 208 0
+245 13 0
+245 65 0
+246 33 0
+246 65 0
+246 245 0
+247 169 0
+247 78 0
+248 68 0
+248 17 0
+249 157 0
+249 28 0
+250 65 0
+250 226 0
+251 133 0
+251 87 0
+251 30 0
+251 61 0
+251 139 0
+252 131 0
+252 48 0
+252 151 0
+253 52 0
+253 38 0
+253 155 0
+254 242 0
+254 152 0
+255 214 0
+256 28 0
+256 119 0
+256 7 0
+256 249 0
+257 88 0
+257 7 0
+258 31 0
+258 16 0
+258 205 0
+258 230 0
+258 114 0
+259 59 0
+259 78 0
+260 29 0
+260 64 0
+261 94 0
+261 7 0
+261 243 0
+262 76 0
+262 41 0
+263 91 0
+263 192 0
+263 114 0
+263 8 0
+264 236 0
+264 37 0
+264 13 0
+265 12 0
+265 77 0
+265 2 0
+265 184 0
+266 2 0
+267 46 0
+267 20 0
+268 6 0
+268 110 0
+269 52 0
+269 136 0
+270 200 0
+271 254 0
+272 22 0
+272 96 0
+272 170 0
+273 19 0
+273 111 0
+273 47 0
+274 56 0
+274 219 0
+274 167 0
+275 210 0
+275 19 0
+276 18 0
+276 227 0
+276 39 0
+277 19 0
+277 39 0
+278 91 0
+279 80 0
+279 11 0
+279 215 0
+280 3 0
+280 13 0
+280 37 0
+280 231 0
+281 231 0
+281 109 0
+281 179 0
+282 97 0
+282 6 0
+282 268 0
+283 62 0
+283 182 0
+284 43 0
+284 51 0
+284 75 0
+284 160 0
+285 236 0
+285 50 0
+285 115 0
+286 161 0
+286 90 0
+287 49 0
+288 13 0
+288 108 0
+289 47 0
+289 180 0
+290 56 0
+290 54 0
+291 8 0
+292 114 0
+292 230 0
+292 234 0
+293 249 0
+293 7 0
+293 69 0
+293 157 0
+294 7 0
+294 128 0
+294 101 0
+295 34 0
+295 204 0
+296 25 0
+296 24 0
+297 139 0
+297 191 0
+297 54 0
+298 27 0
+298 104 0
+298 25 0
+299 8 0
+299 263 0
+299 114 0
+299 292 0
+300 103 0
+300 192 0
+301 205 0
+301 230 0
+301 258 0
+302 109 0
+302 74 0
+302 55 0
+302 179 0
+302 281 0
+303 230 0
+303 301 0
+304 263 0
+304 299 0
+305 221 0
+305 10 0
+305 25 0
+305 223 0
+307 7 0
+307 176 0
+307 69 0
+308 114 0
+308 31 0
+309 44 0
+309 51 0
+309 239 0
+309 43 0
+310 57 0
+310 92 0
+310 162 0
+310 2 0
+310 20 0
+311 263 0
+311 114 0
+311 299 0
+312 130 0
+312 20 0
+312 46 0
+312 173 0
+313 219 0
+313 274 0
+314 59 0
+314 27 0
+314 209 0
+315 147 0
+315 255 0
+316 5 0
+316 207 0
+316 29 0
+316 161 0
+317 54 0
+317 156 0
+317 59 0
+318 167 0
+318 195 0
+318 122 0
+319 183 0
+319 4 0
+320 153 0
+320 34 0
+320 35 0
+321 88 0
+321 93 0
+321 69 0
+321 67 0
+321 7 0
+322 70 0
+322 242 0
+322 254 0
+322 271 0
+323 98 0
+323 39 0
+324 66 0
+324 73 0
+324 260 0
+324 29 0
+325 31 0
+325 229 0
+326 119 0
+326 131 0
+326 252 0
+326 151 0
+327 290 0
+327 54 0
+328 150 0
+328 3 0
+328 29 0
+329 38 0
+329 253 0
+329 52 0
+330 184 0
+330 16 0
+332 326 0
+332 151 0
+332 45 0
+333 11 0
+333 143 0
+333 124 0
+334 274 0
+335 138 0
+335 50 0
+335 18 0
+336 238 0
+336 235 0
+337 19 0
+337 165 0
+337 8 0
+338 225 0
+338 149 0
+338 146 0
+338 3 0
+339 45 0
+339 335 0
+340 29 0
+340 150 0
+340 328 0
+341 326 0
+341 45 0
+342 29 0
+342 149 0
+342 338 0
+342 150 0
+343 318 0
+343 167 0
+343 306 0
+344 245 0
+344 33 0
+344 246 0
+345 125 0
+345 178 0
+345 224 0
+345 78 0
+345 237 0
+346 3 0
+346 58 0
+347 15 0
+347 88 0
+347 257 0
+348 52 0
+348 218 0
+348 84 0
+348 136 0
+349 17 0
+349 52 0
+349 269 0
+350 245 0
+350 13 0
+350 33 0
+350 344 0
+351 177 0
+351 105 0
+351 227 0
+352 24 0
+353 9 0
+353 8 0
+354 151 0
+354 18 0
+354 45 0
+355 165 0
+355 337 0
+356 299 0
+356 292 0
+356 234 0
+356 8 0
+357 287 0
+357 49 0
+357 127 0
+357 222 0
+357 207 0
+358 266 0
+358 35 0
+358 34 0
+358 2 0
+359 270 0
+359 164 0
+360 203 0
+360 55 0
+360 137 0
+361 17 0
+361 168 0
+361 101 0
+361 36 0
+362 303 0
+362 301 0
+362 205 0
+362 234 0
+362 230 0
+363 156 0
+363 327 0
+364 89 0
+364 37 0
+364 81 0
+365 52 0
+365 17 0
+365 49 0
+365 112 0
+366 141 0
+366 16 0
+366 75 0
+367 360 0
+367 180 0
+367 55 0
+368 286 0
+368 202 0
+368 5 0
+368 161 0
+369 91 0
+369 263 0
+369 126 0
+369 8 0
+370 71 0
+370 51 0
+370 309 0
+370 44 0
+370 70 0
+371 360 0
+371 137 0
+371 180 0
+371 367 0
+372 286 0
+372 90 0
+372 202 0
+372 368 0
+373 225 0
+373 150 0
+374 166 0
+375 306 0
+376 6 0
+376 110 0
+376 268 0
+377 213 0
+377 96 0
+377 170 0
+378 367 0
+378 180 0
+379 375 0
+379 343 0
+379 306 0
+380 169 0
+380 334 0
+380 274 0
+381 10 0
+381 54 0
+381 209 0
+382 45 0
+382 80 0
+382 215 0
+383 35 0
+384 216 0
+384 170 0
+385 10 0
+385 221 0
+385 110 0
+386 62 0
+386 182 0
+386 189 0
+386 77 0
+387 347 0
+387 7 0
+388 296 0
+388 130 0
+388 25 0
+389 100 0
+389 199 0
+389 29 0
+389 23 0
+389 226 0
+390 387 0
+390 347 0
+391 134 0
+391 13 0
+391 250 0
+391 226 0
+392 55 0
+392 144 0
+392 58 0
+392 3 0
+393 14 0
+394 130 0
+394 388 0
+395 73 0
+395 64 0
+395 260 0
+395 324 0
+396 11 0
+396 45 0
+396 382 0
+397 55 0
+397 47 0
+398 371 0
+399 188 0
+399 12 0
+399 184 0
+400 237 0
+400 95 0
+401 234 0
+401 362 0
+402 21 0
+402 197 0
+402 44 0
+402 154 0
+402 43 0
+403 367 0
+403 360 0
+403 371 0
+404 277 0
+404 39 0
+404 83 0
+404 240 0
+405 154 0
+405 43 0
+405 402 0
+406 176 0
+406 67 0
+406 321 0
+407 336 0
+407 238 0
+408 5 0
+408 21 0
+409 241 0
+409 122 0
+409 117 0
+410 207 0
+410 316 0
+410 5 0
+410 49 0
+411 317 0
+411 156 0
+411 247 0
+411 85 0
+412 162 0
+412 174 0
+412 92 0
+413 141 0
+413 75 0
+413 51 0
+413 291 0
+414 8 0
+414 113 0
+414 165 0
+414 91 0
+415 98 0
+415 142 0
+415 227 0
+415 28 0
+415 83 0
+416 337 0
+416 19 0
+416 103 0
+416 165 0
+417 355 0
+417 165 0
+417 113 0
+417 337 0
+418 210 0
+418 275 0
+418 19 0
+418 12 0
+419 196 0
+419 153 0
+420 100 0
+420 199 0
+421 345 0
+421 78 0
+421 237 0
+422 8 0
+422 132 0
+423 87 0
+424 28 0
+424 12 0
+424 186 0
+424 240 0
+425 127 0
+425 248 0
+425 17 0
+426 380 0
+426 334 0
+426 274 0
+427 29 0
+427 172 0
+427 324 0
+428 298 0
+428 20 0
+428 24 0
+429 331 0
+429 308 0
+429 114 0
+430 202 0
+430 368 0
+430 372 0
+431 219 0
+431 217 0
+431 95 0
+431 167 0
+432 35 0
+432 187 0
+432 93 0
+433 129 0
+433 184 0
+433 330 0
+433 16 0
+434 363 0
+434 156 0
+435 137 0
+435 203 0
+435 360 0
+436 16 0
+436 184 0
+437 374 0
+437 132 0
+438 243 0
+438 7 0
+439 272 0
+439 96 0
+440 342 0
+440 225 0
+441 18 0
+441 45 0
+442 309 0
+442 51 0
+442 239 0
+443 382 0
+443 50 0
+443 80 0
+444 56 0
+444 123 0
+444 178 0
+444 125 0
+444 313 0
+445 112 0
+445 155 0
+445 38 0
+445 365 0
+446 139 0
+446 61 0
+447 100 0
+447 226 0
+447 145 0
+447 40 0
+447 29 0
+448 342 0
+448 225 0
+448 373 0
+448 150 0
+449 1 0
+449 160 0
+449 407 0
+449 336 0
+450 307 0
+450 7 0
+450 94 0
+451 375 0
+451 237 0
+451 78 0
+451 379 0
+452 50 0
+452 138 0
+452 18 0
+453 272 0
+453 439 0
+453 213 0
+453 377 0
+453 170 0
+454 69 0
+454 176 0
+454 406 0
+454 321 0
+455 316 0
+455 207 0
+455 29 0
+456 141 0
+456 413 0
+456 291 0
+457 61 0
+457 59 0
+457 191 0
+458 421 0
+458 78 0
+458 451 0
+458 237 0
+459 8 0
+459 9 0
+459 152 0
+459 5 0
+459 42 0
+460 85 0
+460 59 0
+460 317 0
+460 411 0
+461 194 0
+461 87 0
+461 220 0
+461 4 0
+461 30 0
+462 347 0
+462 15 0
+462 107 0
+463 74 0
+463 302 0
+464 8 0
+464 166 0
+464 374 0
+465 94 0
+465 261 0
+465 307 0
+466 18 0
+466 81 0
+466 364 0
+466 37 0
+466 115 0
+467 30 0
+467 20 0
+467 27 0
+467 314 0
+467 59 0
+468 70 0
+468 370 0
+468 44 0
+469 110 0
+469 221 0
+469 305 0
+469 223 0
+470 56 0
+470 297 0
+470 59 0
+471 181 0
+471 34 0
+471 116 0
+472 411 0
+473 164 0
+473 200 0
+474 403 0
+474 360 0
+474 398 0
+474 371 0
+475 227 0
+475 276 0
+475 18 0
+476 45 0
+476 441 0
+476 18 0
+476 335 0
+477 132 0
+477 66 0
+477 324 0
+477 427 0
+478 357 0
+478 127 0
+479 41 0
+479 163 0
+480 67 0
+480 406 0
+480 176 0
+480 307 0
+481 429 0
+481 114 0
+481 129 0
+482 227 0
+482 351 0
+482 28 0
+483 251 0
+483 133 0
+483 87 0
+484 328 0
+484 3 0
+484 8 0
+485 84 0
+485 218 0
+485 79 0
+485 60 0
+485 7 0
+486 78 0
+486 117 0
+486 195 0
+486 318 0
+487 19 0
+487 89 0
+487 364 0
+487 81 0
+488 296 0
+488 394 0
+488 388 0
+489 72 0
+489 241 0
+489 117 0
+489 169 0
+490 241 0
+490 72 0
+490 167 0
+491 438 0
+491 480 0
+491 261 0
+491 243 0
+492 211 0
+492 171 0
+493 448 0
+493 373 0
+493 150 0
+494 65 0
+494 208 0
+494 245 0
+495 202 0
+495 90 0
+495 42 0
+496 126 0
+496 369 0
+496 263 0
+497 354 0
+497 151 0
+497 252 0
+497 48 0
+497 105 0
+498 283 0
+498 182 0
+499 254 0
+499 152 0
+499 9 0
+499 322 0
+500 115 0
+500 50 0
+500 18 0
+501 283 0
+501 498 0
+501 182 0
+501 386 0
+501 62 0
+502 420 0
+502 199 0
+502 389 0
+502 100 0
+503 3 0
+503 179 0
+503 55 0
+504 59 0
+504 56 0
+505 184 0
+505 433 0
+505 129 0
+505 188 0
+507 265 0
+507 77 0
+507 386 0
+507 189 0
+508 428 0
+508 24 0
+509 183 0
+509 216 0
+509 384 0
+509 170 0
+510 15 0
+510 7 0
+510 60 0
+511 78 0
+511 247 0
+511 169 0
+511 117 0
+511 486 0
+512 490 0
+512 167 0
+512 122 0
+512 409 0
+512 241 0
+513 257 0
+513 7 0
+513 387 0
+513 347 0
+514 466 0
+514 364 0
+514 37 0
+515 110 0
+515 97 0
+515 282 0
+515 268 0
+516 327 0
+517 89 0
+517 487 0
+517 19 0
+517 47 0
+518 169 0
+518 380 0
+519 2 0
+519 46 0
+519 267 0
+519 20 0
+520 3 0
+520 338 0
+520 146 0
+520 13 0
+521 79 0
+521 60 0
+522 377 0
+522 96 0
+522 82 0
+522 170 0
+523 145 0
+523 226 0
+523 250 0
+524 10 0
+524 198 0
+524 6 0
+524 5 0
+525 428 0
+525 20 0
+525 130 0
+525 352 0
+525 24 0
+526 73 0
+526 66 0
+527 476 0
+527 45 0
+527 441 0
+528 130 0
+528 488 0
+528 296 0
+528 24 0
+529 471 0
+529 181 0
+529 110 0
+529 34 0
+530 498 0
+530 283 0
+530 182 0
+531 342 0
+531 225 0
+531 448 0
+532 446 0
+532 139 0
+532 251 0
+533 394 0
+533 488 0
+533 528 0
+533 130 0
+534 236 0
+534 115 0
+534 466 0
+535 52 0
+535 112 0
+535 506 0
+536 506 0
+536 535 0
+536 5 0
+537 46 0
+537 34 0
+537 295 0
+537 204 0
+538 186 0
+538 418 0
+539 228 0
+539 381 0
+539 54 0
+540 211 0
+540 492 0
+540 171 0
+541 365 0
+541 445 0
+541 38 0
+541 52 0
+542 83 0
+542 14 0
+542 118 0
+543 76 0
+543 262 0
+543 41 0
+543 147 0
+543 29 0
+544 159 0
+545 306 0
+545 343 0
+545 167 0
+545 237 0
+546 146 0
+546 149 0
+546 13 0
+547 347 0
+547 462 0
+547 107 0
+548 62 0
+548 501 0
+548 386 0
+549 155 0
+550 218 0
+550 485 0
+550 348 0
+551 85 0
+551 78 0
+551 259 0
+552 165 0
+553 13 0
+553 245 0
+553 208 0
+553 65 0
+554 34 0
+554 110 0
+554 204 0
+555 427 0
+555 29 0
+555 8 0
+556 466 0
+556 37 0
+557 159 0
+557 232 0
+558 481 0
+558 129 0
+558 308 0
+558 429 0
+559 516 0
+559 56 0
+559 169 0
+559 156 0
+559 434 0
+560 134 0
+560 391 0
+560 226 0
+561 480 0
+561 307 0
+561 465 0
+561 261 0
+561 491 0
+562 70 0
+562 9 0
+562 71 0
+562 370 0
+563 81 0
+563 487 0
+564 110 0
+564 469 0
+564 223 0
+565 5 0
+565 459 0
+565 152 0
+566 19 0
+566 418 0
+566 275 0
+567 108 0
+567 13 0
+567 32 0
+568 557 0
+568 83 0
+568 39 0
+568 232 0
+569 6 0
+569 376 0
+570 27 0
+570 10 0
+570 209 0
+570 314 0
+571 172 0
+571 427 0
+572 507 0
+572 77 0
+572 386 0
+573 20 0
+573 298 0
+574 133 0
+574 483 0
+575 470 0
+575 191 0
+575 59 0
+576 51 0
+576 164 0
+576 8 0
+576 291 0
+576 413 0
+577 45 0
+577 50 0
+577 443 0
+577 382 0
+578 139 0
+578 220 0
+578 133 0
+579 210 0
+579 275 0
+580 572 0
+580 77 0
+580 386 0
+581 28 0
+581 424 0
+581 240 0
+582 144 0
+582 392 0
+582 55 0
+583 96 0
+583 213 0
+583 439 0
+584 28 0
+584 48 0
+584 131 0
+584 119 0
+584 256 0
+585 228 0
+585 209 0
+585 381 0
+585 539 0
+586 325 0
+586 229 0
+586 114 0
+586 308 0
+586 31 0
+587 471 0
+587 34 0
+588 582 0
+588 55 0
+588 144 0
+589 244 0
+589 17 0
+589 248 0
+589 68 0
+590 301 0
+590 205 0
+590 362 0
+591 52 0
+591 535 0
+591 5 0
+591 212 0
+592 383 0
+592 35 0
+592 196 0
+592 419 0
+593 521 0
+593 60 0
+593 485 0
+593 79 0
+594 587 0
+594 34 0
+594 116 0
+594 471 0
+595 388 0
+595 296 0
+595 488 0
+596 291 0
+596 8 0
+597 430 0
+597 368 0
+598 278 0
+598 91 0
+599 308 0
+599 586 0
+599 114 0
+600 158 0
+600 171 0
+600 492 0
+600 17 0
+601 422 0
+601 8 0
+601 464 0
+602 28 0
+602 415 0
+603 165 0
+603 552 0
+603 278 0
+604 235 0
+604 75 0
+604 1 0
+605 125 0
+605 345 0
+605 217 0
+606 508 0
+606 104 0
+606 298 0
+606 428 0
+607 46 0
+607 537 0
+607 204 0
+607 173 0
+607 312 0
+608 159 0
+608 544 0
+608 118 0
+608 14 0
+608 393 0
+609 323 0
+609 39 0
+609 142 0
+609 98 0
+610 52 0
+610 535 0
+610 591 0
+611 286 0
+611 161 0
+611 90 0
+612 487 0
+612 563 0
+612 81 0
+613 118 0
+613 544 0
+613 232 0
+614 555 0
+614 172 0
+614 427 0
+615 127 0
+615 222 0
+615 357 0
+616 207 0
+616 410 0
+616 49 0
+616 287 0
+616 357 0
+617 347 0
+617 390 0
+617 387 0
+618 471 0
+618 116 0
+618 35 0
+618 106 0
+618 181 0
+619 513 0
+619 387 0
+619 390 0
+619 347 0
+620 70 0
+620 322 0
+620 499 0
+620 9 0
+620 562 0
+621 445 0
+621 38 0
+621 541 0
+622 339 0
+622 577 0
+622 45 0
+623 398 0
+623 474 0
+623 360 0
+623 371 0
+624 133 0
+625 431 0
+625 605 0
+625 237 0
+625 95 0
+626 164 0
+626 473 0
+626 200 0
+626 270 0
+626 359 0
+627 380 0
+627 274 0
+628 411 0
+628 472 0
+628 156 0
+628 169 0
+629 452 0
+629 138 0
+629 18 0
+630 156 0
+630 628 0
+630 472 0
+630 411 0
+631 425 0
+631 127 0
+631 49 0
+631 68 0
+631 248 0
+632 605 0
+633 505 0
+633 184 0
+633 433 0
+634 422 0
+634 601 0
+634 464 0
+634 374 0
+634 437 0
+635 569 0
+635 6 0
+635 110 0
+635 376 0
+636 516 0
+636 434 0
+637 391 0
+637 65 0
+637 250 0
+638 464 0
+639 499 0
+639 322 0
+639 271 0
+639 254 0
+640 5 0
+640 319 0
+640 524 0
+641 184 0
+641 16 0
+641 330 0
+642 577 0
+642 622 0
+642 339 0
+643 492 0
+643 425 0
+643 17 0
+643 600 0
+644 146 0
+644 546 0
+644 13 0
+644 520 0
+645 21 0
+645 57 0
+645 82 0
+645 96 0
+646 319 0
+646 640 0
+646 5 0
+647 408 0
+647 21 0
+647 645 0
+647 96 0
+647 5 0
+648 7 0
+648 101 0
+648 168 0
+649 604 0
+649 1 0
+649 235 0
+650 237 0
+650 451 0
+650 375 0
+650 306 0
+651 22 0
+651 183 0
+651 319 0
+651 646 0
+651 5 0
+652 11 0
+652 124 0
+653 6 0
+653 10 0
+653 110 0
+654 485 0
+654 84 0
+654 550 0
+655 130 0
+655 24 0
+655 352 0
+655 525 0
+656 170 0
+656 190 0
+657 500 0
+657 115 0
+657 285 0
+658 128 0
+658 7 0
+658 119 0
+658 11 0
+658 652 0
+659 518 0
+659 380 0
+659 627 0
+659 102 0
+659 169 0
+660 483 0
+660 574 0
+660 87 0
+661 118 0
+661 98 0
+661 83 0
+661 542 0
+662 164 0
+662 8 0
+662 576 0
+663 135 0
+663 119 0
+663 326 0
+664 342 0
+664 149 0
+664 338 0
+665 438 0
+665 7 0
+665 67 0
+666 548 0
+666 386 0
+666 62 0
+667 253 0
+667 38 0
+667 549 0
+667 155 0
+668 242 0
+668 70 0
+668 44 0
+668 152 0
+668 254 0
+669 332 0
+669 341 0
+669 326 0
+670 482 0
+670 351 0
+670 105 0
+670 48 0
+670 28 0
+671 270 0
+671 353 0
+671 8 0
+672 15 0
+672 6 0
+672 88 0
+673 176 0
+673 454 0
+673 69 0
+674 588 0
+674 58 0
+674 144 0
+675 18 0
+675 354 0
+675 497 0
+675 105 0
+675 177 0
+676 110 0
+676 564 0
+677 528 0
+677 296 0
+677 24 0
+678 150 0
+678 29 0
+678 342 0
+679 555 0
+679 8 0
+679 422 0
+679 172 0
+679 614 0
+680 284 0
+680 75 0
+681 239 0
+681 442 0
+682 163 0
+682 143 0
+682 11 0
+682 147 0
+683 638 0
+683 464 0
+683 601 0
+684 19 0
+684 81 0
+684 201 0
+685 29 0
+685 40 0
+685 33 0
+685 32 0
+685 149 0
+686 538 0
+686 418 0
+687 78 0
+687 85 0
+687 247 0
+688 322 0
+688 242 0
+688 254 0
+689 337 0
+689 417 0
+690 65 0
+690 637 0
+690 391 0
+690 13 0
+690 553 0
+691 682 0
+691 163 0
+691 143 0
+692 275 0
+692 579 0
+692 210 0
+692 99 0
+692 19 0
+693 446 0
+693 532 0
+694 137 0
+694 203 0
+695 146 0
+695 520 0
+695 338 0
+696 624 0
+696 423 0
+696 660 0
+696 574 0
+696 133 0
+697 169 0
+697 56 0
+697 274 0
+698 381 0
+698 10 0
+698 139 0
+698 54 0
+699 172 0
+699 132 0
+699 477 0
+700 515 0
+700 110 0
+700 529 0
+700 181 0
+700 97 0
+701 66 0
+701 324 0
+701 477 0
+702 2 0
+702 34 0
+702 46 0
+702 519 0
+703 630 0
+703 156 0
+703 628 0
+704 90 0
+704 495 0
+705 43 0
+705 21 0
+705 402 0
+706 422 0
+706 634 0
+706 437 0
+706 132 0
+707 2 0
+707 162 0
+707 436 0
+707 184 0
+708 147 0
+708 315 0
+708 255 0
+708 214 0
+709 683 0
+709 464 0
+709 601 0
+710 406 0
+710 454 0
+710 176 0
+711 173 0
+711 204 0
+711 110 0
+712 171 0
+712 158 0
+712 41 0
+713 452 0
+713 50 0
+713 335 0
+713 138 0
+714 476 0
+714 335 0
+714 339 0
+714 45 0
+715 538 0
+715 686 0
+715 418 0
+715 19 0
+715 240 0
+716 170 0
+716 57 0
+716 20 0
+716 4 0
+717 48 0
+717 497 0
+717 252 0
+718 615 0
+718 127 0
+718 222 0
+719 305 0
+719 10 0
+719 25 0
+720 394 0
+720 130 0
+721 663 0
+721 119 0
+722 404 0
+722 240 0
+722 19 0
+722 277 0
+723 105 0
+723 351 0
+723 177 0
+724 588 0
+724 55 0
+725 551 0
+725 259 0
+725 59 0
+725 85 0
+726 43 0
+726 57 0
+726 645 0
+726 21 0
+727 674 0
+727 588 0
+728 56 0
+728 444 0
+728 313 0
+728 274 0
+729 422 0
+729 679 0
+729 8 0
+730 420 0
+730 502 0
+730 100 0
+731 44 0
+731 70 0
+731 468 0
+732 428 0
+732 298 0
+732 573 0
+732 20 0
+733 663 0
+733 326 0
+733 341 0
+733 135 0
+734 367 0
+734 180 0
+734 289 0
+734 55 0
+735 374 0
+735 132 0
+735 437 0
+736 55 0
+736 206 0
+736 58 0
+736 588 0
+737 217 0
+737 605 0
+737 625 0
+738 575 0
+738 470 0
+738 191 0
+739 224 0
+739 178 0
+739 444 0
+740 15 0
+740 60 0
+740 26 0
+741 464 0
+741 8 0
+741 166 0
+742 627 0
+742 274 0
+742 167 0
+742 102 0
+742 659 0
+743 422 0
+743 132 0
+743 699 0
+743 172 0
+743 679 0
+744 414 0
+744 278 0
+744 598 0
+744 91 0
+745 326 0
+745 131 0
+745 252 0
+746 636 0
+746 327 0
+746 516 0
+747 31 0
+747 308 0
+747 558 0
+747 129 0
+747 16 0
+748 380 0
+748 169 0
+748 697 0
+748 334 0
+749 431 0
+749 737 0
+749 625 0
+750 619 0
+750 513 0
+750 387 0
+751 614 0
+751 172 0
+751 571 0
+751 427 0
+752 105 0
+752 497 0
+752 48 0
+752 670 0
+753 726 0
+753 21 0
+753 705 0
+753 43 0
+754 358 0
+754 35 0
+754 320 0
+754 34 0
+755 738 0
+755 575 0
+755 470 0
+756 552 0
+756 165 0
+756 91 0
+756 278 0
+756 603 0
+757 16 0
+757 258 0
+757 31 0
+757 747 0
+758 430 0
+758 597 0
+758 372 0
+759 15 0
+759 347 0
+759 387 0
+760 412 0
+760 92 0
+760 43 0
+760 160 0
+760 162 0
+761 526 0
+761 66 0
+761 73 0
+762 432 0
+762 187 0
+762 62 0
+762 69 0
+762 93 0
+763 676 0
+763 110 0
+763 469 0
+763 564 0
+764 720 0
+764 394 0
+764 533 0
+764 130 0
+765 88 0
+765 35 0
+765 432 0
+765 93 0
+766 215 0
+766 279 0
+766 11 0
+766 396 0
+766 382 0
+767 687 0
+767 78 0
+767 85 0
+768 298 0
+768 27 0
+768 573 0
+769 149 0
+769 32 0
+769 567 0
+769 13 0
+769 546 0
+770 70 0
+770 370 0
+770 468 0
+771 737 0
+771 749 0
+771 431 0
+771 217 0
+772 565 0
+772 152 0
+772 44 0
+772 21 0
+772 5 0
+773 1 0
+773 16 0
+774 596 0
+774 8 0
+774 141 0
+774 456 0
+774 291 0
+775 100 0
+775 29 0
+775 199 0
+775 420 0
+776 710 0
+776 454 0
+776 176 0
+777 112 0
+777 5 0
+777 536 0
+777 535 0
+778 316 0
+778 5 0
+778 410 0
+779 657 0
+779 285 0
+779 50 0
+779 500 0
+780 247 0
+780 687 0
+780 85 0
+780 411 0
+781 92 0
+781 57 0
+781 726 0
+781 43 0
+781 760 0
+782 524 0
+782 6 0
+782 15 0
+782 5 0
+783 84 0
+783 348 0
+783 550 0
+783 654 0
+784 423 0
+784 87 0
+784 660 0
+785 247 0
+785 687 0
+785 780 0
+786 13 0
+786 134 0
+786 23 0
+786 236 0
+787 638 0
+787 683 0
+787 601 0
+787 8 0
+788 520 0
+788 644 0
+789 662 0
+789 270 0
+790 213 0
+790 583 0
+790 96 0
+791 237 0
+791 306 0
+791 545 0
+792 615 0
+792 357 0
+792 127 0
+793 400 0
+793 237 0
+793 545 0
+793 167 0
+793 95 0
+794 234 0
+794 205 0
+794 63 0
+794 8 0
+795 632 0
+795 605 0
+795 345 0
+795 237 0
+796 561 0
+796 465 0
+796 261 0
+797 443 0
+797 382 0
+798 434 0
+798 636 0
+798 516 0
+798 559 0
+799 504 0
+799 56 0
+799 470 0
+799 59 0
+800 788 0
+800 520 0
+800 146 0
+800 644 0
+801 73 0
+801 132 0
+801 166 0
+802 347 0
+802 88 0
+802 257 0
+803 603 0
+803 414 0
+803 165 0
+804 311 0
+804 299 0
+804 304 0
+804 263 0
+805 13 0
+805 134 0
+805 786 0
+806 419 0
+806 153 0
+806 35 0
+806 383 0
+806 592 0
+807 214 0
+807 255 0
+807 315 0
+807 479 0
+808 104 0
+808 606 0
+808 508 0
+808 24 0
+809 235 0
+809 1 0
+810 261 0
+810 7 0
+810 243 0
+811 366 0
+811 141 0
+811 63 0
+811 16 0
+812 120 0
+812 73 0
+812 801 0
+812 166 0
+813 300 0
+813 192 0
+813 91 0
+813 165 0
+813 103 0
+814 539 0
+814 54 0
+814 228 0
+815 697 0
+815 274 0
+815 334 0
+815 748 0
+816 262 0
+816 41 0
+816 543 0
+817 203 0
+817 371 0
+817 360 0
+818 341 0
+818 669 0
+818 332 0
+818 45 0
+819 736 0
+819 58 0
+819 674 0
+819 727 0
+819 588 0
+820 171 0
+820 712 0
+820 41 0
+820 29 0
+821 18 0
+821 675 0
+821 177 0
+821 227 0
+822 562 0
+822 71 0
+822 370 0
+823 613 0
+823 118 0
+824 387 0
+824 390 0
+824 619 0
+825 135 0
+825 733 0
+825 341 0
+825 45 0
+825 175 0
+826 665 0
+826 67 0
+826 480 0
+827 640 0
+827 220 0
+827 10 0
+827 524 0
+828 710 0
+828 406 0
+829 789 0
+829 662 0
+829 164 0
+829 359 0
+829 270 0
+830 80 0
+830 797 0
+830 443 0
+831 186 0
+831 538 0
+831 715 0
+831 240 0
+831 424 0
+832 133 0
+832 220 0
+832 461 0
+832 87 0
+832 423 0
+833 640 0
+833 646 0
+833 319 0
+834 173 0
+834 711 0
+834 110 0
+834 564 0
+834 223 0
+835 52 0
+835 86 0
+835 212 0
+835 148 0
+835 79 0
+836 236 0
+836 285 0
+836 115 0
+836 534 0
+837 792 0
+837 357 0
+837 478 0
+837 127 0
+838 182 0
+838 35 0
+838 266 0
+838 189 0
+839 482 0
+840 524 0
+840 640 0
+840 827 0
+841 544 0
+841 608 0
+842 582 0
+842 55 0
+842 724 0
+842 588 0
+843 76 0
+843 262 0
+843 543 0
+844 105 0
+844 670 0
+844 351 0
+845 516 0
+845 327 0
+845 290 0
+845 56 0
+846 832 0
+846 423 0
+846 133 0
+847 787 0
+847 8 0
+847 464 0
+847 638 0
+848 29 0
+848 328 0
+848 484 0
+848 8 0
+848 555 0
+849 331 0
+849 429 0
+849 558 0
+850 162 0
+850 1 0
+850 773 0
+850 16 0
+851 54 0
+851 297 0
+851 470 0
+851 56 0
+851 290 0
+852 166 0
+852 741 0
+852 8 0
+853 735 0
+853 374 0
+853 166 0
+853 132 0
+854 179 0
+854 503 0
+854 3 0
+855 234 0
+855 401 0
+855 362 0
+855 205 0
+855 794 0
+856 83 0
+856 568 0
+857 250 0
+857 65 0
+858 807 0
+858 479 0
+858 163 0
+858 214 0
+859 44 0
+859 309 0
+859 43 0
+859 154 0
+859 402 0
+860 203 0
+860 694 0
+860 137 0
+860 371 0
+860 817 0
+861 427 0
+861 172 0
+861 699 0
+861 477 0
+862 557 0
+862 159 0
+862 608 0
+862 856 0
+863 605 0
+863 632 0
+863 795 0
+863 237 0
+863 625 0
+864 343 0
+864 379 0
+864 451 0
+864 78 0
+864 318 0
+865 802 0
+865 347 0
+865 88 0
+866 387 0
+866 15 0
+866 759 0
+867 17 0
+867 349 0
+867 269 0
+867 136 0
+867 84 0
+868 423 0
+868 624 0
+868 133 0
+868 846 0
+869 8 0
+869 126 0
+870 597 0
+870 368 0
+870 372 0
+870 758 0
+871 115 0
+871 18 0
+871 466 0
+872 387 0
+872 7 0
+872 15 0
+872 866 0
+873 170 0
+873 216 0
+873 22 0
+873 272 0
+874 256 0
+874 249 0
+874 28 0
+875 55 0
+875 179 0
+875 302 0
+876 235 0
+876 809 0
+876 1 0
+876 449 0
+876 336 0
+877 176 0
+877 406 0
+877 828 0
+877 710 0
+878 704 0
+878 495 0
+878 202 0
+879 789 0
+879 662 0
+879 829 0
+880 360 0
+880 137 0
+880 435 0
+881 797 0
+881 830 0
+881 80 0
+881 382 0
+882 544 0
+882 159 0
+882 232 0
+882 613 0
+883 191 0
+883 738 0
+883 470 0
+883 297 0
+884 31 0
+884 114 0
+884 229 0
+885 803 0
+885 603 0
+885 278 0
+885 744 0
+885 414 0
+886 299 0
+886 804 0
+886 311 0
+887 235 0
+887 160 0
+887 284 0
+887 680 0
+887 75 0
+888 227 0
+888 39 0
+889 547 0
+889 107 0
+889 88 0
+889 347 0
+890 20 0
+890 312 0
+890 130 0
+890 525 0
+891 109 0
+891 121 0
+891 74 0
+891 463 0
+891 302 0
+892 353 0
+892 671 0
+892 71 0
+892 9 0
+893 189 0
+893 838 0
+893 266 0
+893 2 0
+894 200 0
+894 71 0
+894 892 0
+894 671 0
+894 270 0
+895 393 0
+895 14 0
+895 542 0
+896 823 0
+896 118 0
+896 608 0
+896 544 0
+896 613 0
+897 357 0
+897 49 0
+897 127 0
+898 784 0
+898 660 0
+898 696 0
+898 423 0
+899 337 0
+899 689 0
+899 417 0
+899 113 0
+899 8 0
+900 440 0
+900 342 0
+900 338 0
+900 225 0
+901 739 0
+901 444 0
+901 123 0
+901 224 0
+902 251 0
+902 61 0
+902 446 0
+902 693 0
+902 532 0
+903 51 0
+903 239 0
+903 681 0
+903 442 0
+904 90 0
+904 611 0
+904 161 0
+905 237 0
+905 650 0
+905 306 0
+905 791 0
+906 318 0
+906 864 0
+906 78 0
+906 486 0
+907 690 0
+907 13 0
+907 553 0
+908 573 0
+908 768 0
+908 27 0
+908 53 0
+908 20 0
+909 640 0
+909 319 0
+909 827 0
+910 734 0
+910 289 0
+910 47 0
+910 397 0
+910 55 0
+911 145 0
+911 523 0
+911 65 0
+912 412 0
+912 174 0
+912 92 0
+913 5 0
+913 15 0
+913 740 0
+913 26 0
+913 60 0
+914 61 0
+914 251 0
+914 30 0
+914 59 0
+915 694 0
+915 137 0
+915 860 0
+916 288 0
+916 108 0
+916 32 0
+916 33 0
+916 13 0
+917 61 0
+917 191 0
+917 185 0
+917 139 0
+918 306 0
+918 545 0
+918 791 0
+919 602 0
+919 415 0
+919 227 0
+919 482 0
+919 839 0
+920 331 0
+920 849 0
+920 558 0
+920 308 0
+920 429 0
+921 56 0
+921 799 0
+922 448 0
+922 493 0
+922 150 0
+923 707 0
+923 162 0
+923 16 0
+923 436 0
+924 838 0
+924 266 0
+925 487 0
+925 89 0
+925 364 0
+926 238 0
+926 407 0
+926 449 0
+926 160 0
+926 235 0
+927 131 0
+927 584 0
+927 48 0
+927 252 0
+928 542 0
+928 83 0
+928 856 0
+928 393 0
+928 895 0
+929 266 0
+929 924 0
+929 35 0
+929 358 0
+930 795 0
+930 237 0
+930 863 0
+931 2 0
+931 893 0
+931 266 0
+932 636 0
+932 434 0
+932 363 0
+932 327 0
+932 746 0
+933 823 0
+933 613 0
+933 118 0
+934 363 0
+934 156 0
+934 317 0
+934 54 0
+934 327 0
+935 41 0
+935 479 0
+935 807 0
+935 315 0
+935 147 0
+936 450 0
+936 94 0
+936 307 0
+937 231 0
+937 121 0
+938 685 0
+938 40 0
+938 33 0
+939 856 0
+939 568 0
+939 557 0
+939 862 0
+940 820 0
+940 41 0
+940 76 0
+940 29 0
+941 531 0
+941 342 0
+942 29 0
+942 211 0
+942 540 0
+942 171 0
+943 936 0
+943 94 0
+943 465 0
+943 307 0
+944 378 0
+944 367 0
+944 371 0
+944 180 0
+945 712 0
+945 158 0
+945 36 0
+945 41 0
+946 583 0
+946 213 0
+947 665 0
+947 826 0
+947 480 0
+947 491 0
+947 438 0
+948 141 0
+948 8 0
+948 63 0
+949 559 0
+949 516 0
+949 845 0
+949 56 0
+950 549 0
+950 667 0
+950 38 0
+950 445 0
+950 155 0
+951 5 0
+951 591 0
+951 535 0
+951 506 0
+951 536 0
+952 453 0
+952 439 0
+952 583 0
+952 946 0
+952 213 0
+953 28 0
+953 602 0
+953 919 0
+953 839 0
+953 482 0
+954 643 0
+954 492 0
+954 211 0
+954 127 0
+954 425 0
+955 725 0
+955 59 0
+955 85 0
+956 628 0
+956 169 0
+956 247 0
+956 411 0
+957 27 0
+957 467 0
+957 20 0
+958 289 0
+958 180 0
+958 47 0
+959 941 0
+959 342 0
+959 440 0
+959 225 0
+959 531 0
+960 12 0
+960 418 0
+960 538 0
+960 186 0
+961 165 0
+961 416 0
+961 103 0
+961 813 0
+962 2 0
+962 265 0
+963 176 0
+963 710 0
+963 776 0
+964 125 0
+964 217 0
+964 219 0
+964 313 0
+964 444 0
+965 210 0
+965 12 0
+965 103 0
+965 99 0
+965 692 0
+966 761 0
+966 66 0
+966 140 0
+967 911 0
+967 523 0
+967 250 0
+967 857 0
+967 65 0
+968 652 0
+968 124 0
+968 101 0
+968 128 0
+968 658 0
+969 335 0
+969 50 0
+969 577 0
+969 642 0
+969 339 0
+970 775 0
+970 100 0
+970 29 0
+971 129 0
+971 12 0
+972 470 0
+972 799 0
+972 921 0
+972 56 0
+973 624 0
+973 868 0
+973 423 0
+973 696 0
+974 612 0
+974 81 0
+974 19 0
+974 487 0
+975 556 0
+975 37 0
+975 236 0
+975 534 0
+975 466 0
+976 663 0
+976 135 0
+977 827 0
+977 909 0
+977 319 0
+977 4 0
+977 220 0
+978 10 0
+978 381 0
+978 209 0
+978 570 0
+979 13 0
+979 644 0
+979 546 0
+980 7 0
+980 293 0
+980 249 0
+980 256 0
+981 109 0
+981 231 0
+981 937 0
+981 121 0
+982 929 0
+982 924 0
+982 838 0
+982 35 0
+983 966 0
+983 140 0
+983 73 0
+983 761 0
+984 671 0
+984 8 0
+984 662 0
+984 789 0
+984 270 0
+985 878 0
+985 202 0
+985 372 0
+985 90 0
+985 704 0
+986 18 0
+986 821 0
+986 227 0
+986 475 0
+987 57 0
+987 716 0
+987 170 0
+987 656 0
+987 190 0
+988 856 0
+988 862 0
+988 608 0
+988 393 0
+988 928 0
+989 77 0
+989 12 0
+989 62 0
+990 888 0
+990 227 0
+990 142 0
+990 39 0
+991 841 0
+991 608 0
+991 159 0
+991 544 0
+992 399 0
+992 188 0
+992 129 0
+992 971 0
+992 12 0
+993 618 0
+993 35 0
+993 106 0
+994 672 0
+994 88 0
+994 889 0
+994 107 0
+994 15 0
+995 976 0
+995 135 0
+995 119 0
+995 721 0
+995 663 0
+996 485 0
+996 7 0
+996 84 0
+997 507 0
+997 189 0
+997 2 0
+997 962 0
+997 265 0
+998 496 0
+998 263 0
+998 8 0
+998 869 0
+998 126 0
+999 392 0
+999 58 0
+999 346 0
+999 3 0
+1000 154 0
+1000 405 0
+1000 402 0
diff --git a/test/planar_input_graphs/pentakis_dodecahedron.leda b/test/planar_input_graphs/pentakis_dodecahedron.leda
new file mode 100644
index 000000000..eba98dc50
--- /dev/null
+++ b/test/planar_input_graphs/pentakis_dodecahedron.leda
@@ -0,0 +1,127 @@
+LEDA.GRAPH // dual graph of truncated icosahedron (known from football)
+int
+int
+32
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+90
+1 2 0
+2 3 0
+3 4 0
+4 5 0
+5 1 0
+6 7 0
+7 8 0
+8 9 0
+9 10 0
+10 6 0
+11 12 0
+12 13 0
+13 14 0
+14 15 0
+15 16 0
+16 17 0
+17 18 0
+18 19 0
+19 20 0
+20 11 0
+1 11 0
+2 13 0
+3 15 0
+4 17 0
+5 19 0
+6 12 0
+7 14 0
+8 16 0
+9 18 0
+10 20 0
+21 1 0
+21 2 0
+21 3 0
+21 4 0
+21 5 0
+22 6 0
+22 7 0
+22 8 0
+22 9 0
+22 10 0
+23 1 0
+23 2 0
+23 11 0
+23 12 0
+23 13 0
+24 6 0
+24 7 0
+24 12 0
+24 13 0
+24 14 0
+25 2 0
+25 3 0
+25 13 0
+25 14 0
+25 15 0
+26 7 0
+26 8 0
+26 14 0
+26 15 0
+26 16 0
+27 3 0
+27 4 0
+27 15 0
+27 16 0
+27 17 0
+28 8 0
+28 9 0
+28 16 0
+28 17 0
+28 18 0
+29 4 0
+29 5 0
+29 17 0
+29 18 0
+29 19 0
+30 9 0
+30 10 0
+30 18 0
+30 19 0
+30 20 0
+31 1 0
+31 5 0
+31 11 0
+31 19 0
+31 20 0
+32 6 0
+32 10 0
+32 11 0
+32 12 0
+32 20 0
diff --git a/test/planar_vertex_six_coloring.cpp b/test/planar_vertex_six_coloring.cpp
new file mode 100644
index 000000000..9b11a7087
--- /dev/null
+++ b/test/planar_vertex_six_coloring.cpp
@@ -0,0 +1,216 @@
+//=======================================================================
+// Copyright 2024
+// Authors: Hermann Stamm-Wilbrandt
+//
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//=======================================================================
+//
+// Demonstrates sequential_vertex_coloring() forced to take 15 colors
+// on graph built with "create(15, g)", and planar_vertex_six_coloring()
+// taking 6 colors only (both linear time algorithms).
+//
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace boost;
+
+typedef adjacency_list< listS, vecS, undirectedS > Graph;
+typedef graph_traits< Graph >::vertices_size_type vertices_size_type;
+typedef graph_traits< Graph >::vertex_descriptor vertex_descriptor;
+typedef graph_traits< Graph >::edge_descriptor edge_descriptor;
+
+
+edge_descriptor create(Graph& g, int k);
+void read_leda_graph(Graph& g, const char* gname);
+
+// time measurements
+clock_t start_;
+#define __(blk) if (output) std::cerr << #blk << " "; start_ = clock(); blk \
+ if (output) std::cerr << (clock()-start_)*1.0/CLOCKS_PER_SEC << std::endl;
+
+
+int main(int argc, char*argv[])
+{
+ unsigned int k = (argc < 2) ? 15 : atoi(argv[1]);
+ bool output = argc > 2;
+
+ Graph g;
+ edge_descriptor e;
+
+ __(create(g, k);)
+
+ BOOST_TEST(num_vertices(g) == 987); // fib(k+1)
+ BOOST_TEST(num_edges(g) == 1595); // fib(k+2)-2
+
+ std::vector< vertices_size_type > color_vec(num_vertices(g));
+ auto color = make_container_vertex_map(color_vec, g);
+
+ __(vertices_size_type num_colors = sequential_vertex_coloring(g, color);)
+
+ BOOST_TEST(num_colors == k);
+ BGL_FORALL_EDGES(e, g, Graph)
+ { BOOST_ASSERT(get(color, source(e, g)) != get(color, target(e, g))); }
+
+ __(vertices_size_type num_color6 = planar_vertex_six_coloring(g, color);)
+
+ BOOST_TEST(num_color6 == 6);
+ BGL_FORALL_EDGES(e, g, Graph)
+ { BOOST_ASSERT(get(color, source(e, g)) != get(color, target(e, g))); }
+
+ if (output)
+ {
+ std::cerr << num_vertices(g) << "/" << num_edges(g)
+ << " vertices/edges" << std::endl;
+ std::cerr << num_colors << "/" << num_color6
+ << " colors used" << std::endl;
+ }
+
+
+ __(read_leda_graph(g, "planar_input_graphs/pentakis_dodecahedron.leda");)
+
+ color_vec.resize(num_vertices(g));
+ color = make_container_vertex_map(color_vec, g);
+
+ BOOST_TEST(num_vertices(g) == 32);
+ BOOST_TEST(num_edges(g) == 3*32-6);
+
+ __(num_colors = sequential_vertex_coloring(g, color);)
+
+ BOOST_TEST(num_colors == 5);
+ BGL_FORALL_EDGES(e, g, Graph)
+ { BOOST_ASSERT(get(color, source(e, g)) != get(color, target(e, g))); }
+
+ __(num_color6 = planar_vertex_six_coloring(g, color);)
+
+ BOOST_TEST(num_color6 == 4);
+ BGL_FORALL_EDGES(e, g, Graph)
+ { BOOST_ASSERT(get(color, source(e, g)) != get(color, target(e, g))); }
+
+ if (output)
+ {
+ std::cerr << num_vertices(g) << "/" << num_edges(g)
+ << " vertices/edges" << std::endl;
+ std::cerr << num_colors << "/" << num_color6
+ << " colors used" << std::endl;
+ }
+
+
+ __(read_leda_graph(g, "planar_input_graphs/maximal_planar_1000.leda");)
+
+ color_vec.resize(num_vertices(g));
+ color = make_container_vertex_map(color_vec, g);
+
+ BOOST_TEST(num_vertices(g) == 1000);
+ BOOST_TEST(num_edges(g) == 3*1000-6);
+
+ __(num_colors = sequential_vertex_coloring(g, color);)
+
+ BOOST_TEST(num_colors == 6);
+ BGL_FORALL_EDGES(e, g, Graph)
+ { BOOST_ASSERT(get(color, source(e, g)) != get(color, target(e, g))); }
+
+ __(num_color6 = planar_vertex_six_coloring(g, color);)
+
+ BOOST_TEST(num_color6 == 6);
+ BGL_FORALL_EDGES(e, g, Graph)
+ { BOOST_ASSERT(get(color, source(e, g)) != get(color, target(e, g))); }
+
+ if (output)
+ {
+ std::cerr << num_vertices(g) << "/" << num_edges(g)
+ << " vertices/edges" << std::endl;
+ std::cerr << num_colors << "/" << num_color6
+ << " colors used" << std::endl;
+ }
+
+
+ return boost::report_errors();
+}
+
+
+/*
+ creating C6
+
+ -5-
+ /|\
+...
+ from C5
+ /
+ ---4
+ / /|\ /
+ plus C3 / / | 3
+ / / / |/|\
+ plus C1 2 / / 2 | \
+ / / \ / / / / \| \
+ 0 0---1 0--1 0---1 0
+*/
+edge_descriptor create(Graph& g, int k)
+{
+ if (k < 4)
+ {
+ BOOST_ASSERT(k > 1);
+
+ vertex_descriptor v = add_vertex(g);
+ vertex_descriptor w = add_vertex(g);
+ auto e = add_edge(v, w, g);
+ if (k == 2) return e.first;
+
+ vertex_descriptor x = add_vertex(g);
+ add_edge(v, x, g);
+ return add_edge(w, x, g).first;
+ }
+
+ std::vector es;
+ while (--k > 1) { es.push_back(create(g, k--)); }
+
+ vertex_descriptor v = add_vertex(g);
+ if (k == 1)
+ {
+ vertex_descriptor w = add_vertex(g);
+ add_edge(v, w, g);
+ v = w;
+ }
+
+ edge_descriptor e;
+ for (auto ei = es.rbegin(); ei != es.rend(); ++ei)
+ {
+ add_edge(source(*ei, g), v, g);
+ e = add_edge(target(*ei, g), v, g).first;
+ }
+ return e;
+}
+
+
+void read_leda_graph(Graph& g, const char* gname)
+{
+ int n, m;
+ std::string line;
+
+ std::ifstream in(gname);
+ BOOST_ASSERT(in);
+
+ std::getline(in, line);
+ in >> line >> line >> n;
+
+ g = Graph(n);
+
+ for (int i=1; i <= n; ++i) {
+ in >> line;
+ }
+
+ in >> m;
+ for (int i=1; i <= m; ++i) {
+ int s, t, v;
+ in >> s >> t >> v;
+ add_edge(s-1, t-1, g);
+ }
+}