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