sl@0: //======================================================================= sl@0: // Copyright 2000 University of Notre Dame. sl@0: // Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee sl@0: // sl@0: // Distributed under the Boost Software License, Version 1.0. (See sl@0: // accompanying file LICENSE_1_0.txt or copy at sl@0: // http://www.boost.org/LICENSE_1_0.txt) sl@0: //======================================================================= sl@0: sl@0: #ifndef BOOST_EDGE_CONNECTIVITY sl@0: #define BOOST_EDGE_CONNECTIVITY sl@0: sl@0: // WARNING: not-yet fully tested! sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: namespace boost { sl@0: sl@0: namespace detail { sl@0: sl@0: template sl@0: inline sl@0: std::pair::vertex_descriptor, sl@0: typename graph_traits::degree_size_type> sl@0: min_degree_vertex(Graph& g) sl@0: { sl@0: typedef graph_traits Traits; sl@0: typename Traits::vertex_descriptor p; sl@0: typedef typename Traits::degree_size_type size_type; sl@0: size_type delta = (std::numeric_limits::max)(); sl@0: sl@0: typename Traits::vertex_iterator i, iend; sl@0: for (tie(i, iend) = vertices(g); i != iend; ++i) sl@0: if (degree(*i, g) < delta) { sl@0: delta = degree(*i, g); sl@0: p = *i; sl@0: } sl@0: return std::make_pair(p, delta); sl@0: } sl@0: sl@0: template sl@0: void neighbors(const Graph& g, sl@0: typename graph_traits::vertex_descriptor u, sl@0: OutputIterator result) sl@0: { sl@0: typename graph_traits::adjacency_iterator ai, aend; sl@0: for (tie(ai, aend) = adjacent_vertices(u, g); ai != aend; ++ai) sl@0: *result++ = *ai; sl@0: } sl@0: sl@0: template sl@0: void neighbors(const Graph& g, sl@0: VertexIterator first, VertexIterator last, sl@0: OutputIterator result) sl@0: { sl@0: for (; first != last; ++first) sl@0: neighbors(g, *first, result); sl@0: } sl@0: sl@0: } // namespace detail sl@0: sl@0: // O(m n) sl@0: template sl@0: typename graph_traits::degree_size_type sl@0: edge_connectivity(VertexListGraph& g, OutputIterator disconnecting_set) sl@0: { sl@0: //------------------------------------------------------------------------- sl@0: // Type Definitions sl@0: typedef graph_traits Traits; sl@0: typedef typename Traits::vertex_iterator vertex_iterator; sl@0: typedef typename Traits::edge_iterator edge_iterator; sl@0: typedef typename Traits::out_edge_iterator out_edge_iterator; sl@0: typedef typename Traits::vertex_descriptor vertex_descriptor; sl@0: typedef typename Traits::degree_size_type degree_size_type; sl@0: typedef color_traits Color; sl@0: sl@0: typedef adjacency_list_traits Tr; sl@0: typedef typename Tr::edge_descriptor Tr_edge_desc; sl@0: typedef adjacency_list > > > sl@0: FlowGraph; sl@0: typedef typename graph_traits::edge_descriptor edge_descriptor; sl@0: sl@0: //------------------------------------------------------------------------- sl@0: // Variable Declarations sl@0: vertex_descriptor u, v, p, k; sl@0: edge_descriptor e1, e2; sl@0: bool inserted; sl@0: vertex_iterator vi, vi_end; sl@0: edge_iterator ei, ei_end; sl@0: degree_size_type delta, alpha_star, alpha_S_k; sl@0: std::set S, neighbor_S; sl@0: std::vector S_star, non_neighbor_S; sl@0: std::vector color(num_vertices(g)); sl@0: std::vector pred(num_vertices(g)); sl@0: sl@0: //------------------------------------------------------------------------- sl@0: // Create a network flow graph out of the undirected graph sl@0: FlowGraph flow_g(num_vertices(g)); sl@0: sl@0: typename property_map::type sl@0: cap = get(edge_capacity, flow_g); sl@0: typename property_map::type sl@0: res_cap = get(edge_residual_capacity, flow_g); sl@0: typename property_map::type sl@0: rev_edge = get(edge_reverse, flow_g); sl@0: sl@0: for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) { sl@0: u = source(*ei, g), v = target(*ei, g); sl@0: tie(e1, inserted) = add_edge(u, v, flow_g); sl@0: cap[e1] = 1; sl@0: tie(e2, inserted) = add_edge(v, u, flow_g); sl@0: cap[e2] = 1; // not sure about this sl@0: rev_edge[e1] = e2; sl@0: rev_edge[e2] = e1; sl@0: } sl@0: sl@0: //------------------------------------------------------------------------- sl@0: // The Algorithm sl@0: sl@0: tie(p, delta) = detail::min_degree_vertex(g); sl@0: S_star.push_back(p); sl@0: alpha_star = delta; sl@0: S.insert(p); sl@0: neighbor_S.insert(p); sl@0: detail::neighbors(g, S.begin(), S.end(), sl@0: std::inserter(neighbor_S, neighbor_S.begin())); sl@0: sl@0: std::set_difference(vertices(g).first, vertices(g).second, sl@0: neighbor_S.begin(), neighbor_S.end(), sl@0: std::back_inserter(non_neighbor_S)); sl@0: sl@0: while (!non_neighbor_S.empty()) { // at most n - 1 times sl@0: k = non_neighbor_S.front(); sl@0: sl@0: alpha_S_k = edmunds_karp_max_flow sl@0: (flow_g, p, k, cap, res_cap, rev_edge, &color[0], &pred[0]); sl@0: sl@0: if (alpha_S_k < alpha_star) { sl@0: alpha_star = alpha_S_k; sl@0: S_star.clear(); sl@0: for (tie(vi, vi_end) = vertices(flow_g); vi != vi_end; ++vi) sl@0: if (color[*vi] != Color::white()) sl@0: S_star.push_back(*vi); sl@0: } sl@0: S.insert(k); sl@0: neighbor_S.insert(k); sl@0: detail::neighbors(g, k, std::inserter(neighbor_S, neighbor_S.begin())); sl@0: non_neighbor_S.clear(); sl@0: std::set_difference(vertices(g).first, vertices(g).second, sl@0: neighbor_S.begin(), neighbor_S.end(), sl@0: std::back_inserter(non_neighbor_S)); sl@0: } sl@0: //------------------------------------------------------------------------- sl@0: // Compute edges of the cut [S*, ~S*] sl@0: std::vector in_S_star(num_vertices(g), false); sl@0: typename std::vector::iterator si; sl@0: for (si = S_star.begin(); si != S_star.end(); ++si) sl@0: in_S_star[*si] = true; sl@0: sl@0: degree_size_type c = 0; sl@0: for (si = S_star.begin(); si != S_star.end(); ++si) { sl@0: out_edge_iterator ei, ei_end; sl@0: for (tie(ei, ei_end) = out_edges(*si, g); ei != ei_end; ++ei) sl@0: if (!in_S_star[target(*ei, g)]) { sl@0: *disconnecting_set++ = *ei; sl@0: ++c; sl@0: } sl@0: } sl@0: return c; sl@0: } sl@0: sl@0: } // namespace boost sl@0: sl@0: #endif // BOOST_EDGE_CONNECTIVITY