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 + + + + C++ Boost +

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: +
    +
  1. "Fibonacci graph" (for k=15), with fib(k+1) vertices and fib(k+2)-2 edges +
  2. boost/graph/test/planar_input_graphs/pentakis_dodecahedron.leda +
  3. 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(). + +
+ + + +
Copyright © 2024 +Hermann Stamm-Wilbrandt (hermann@stamm-wilbrandt.de) +
+ + + 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 @@

Table of Contents: the Boost Graph Library
  1. directed_graph
  2. undirected_graph
  3. +
      +
    1. undirected_graph_constant_time_edge_add_and_remove
    2. +
  • 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 + +C++ Boost + +
    + +

    +
    +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

    + +

    + + + + + + + + + + + + + + + + + + + + + +
    ParameterDescriptionDefault
    VertexPropA property map for the graph vertices. 
    EdgePropA property map for the graph edges. 
    GraphPropA property map for the graph itself.
    +

    + +

    Where Defined

    + +

    +boost/graph/undirected_graph_constant_time_edge_add_and_remove.hpp + +

    + +
    +


    + + +
    Copyright © 2024 +Hermann Stamm-Wilbrandt (hermann@stamm-wilbrandt.de) +
    + + + 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); + } +}