Per the documentation, the minimum spanning tree algorithm implemented in boost should work only on undirected graphs. Yet, the following code that provides a directed graph as input to the algorithm seems to work just fine: (while building on MSVC Visual Studio 2019, there are no warnings related to boost)
#include <boost/property_map/property_map.hpp>
#include <boost/config.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/kruskal_min_spanning_tree.hpp>
#include <boost/graph/graph_utility.hpp>
using namespace boost;
typedef adjacency_list <vecS, vecS, directedS, no_property,
property<edge_weight_t, double>>
Graph_vvd_MST;
typedef adjacency_list_traits<vecS, vecS, directedS> Traits_vvd;
property_map<Graph_vvd_MST, edge_weight_t>::type cost;
typedef Traits_vvd::edge_descriptor Edge;
std::vector < Edge > spanning_tree;
int main() {
Graph_vvd_MST g;
add_vertex(g);//0 th index vertex
add_vertex(g);// 1 index vertex
add_vertex(g);// 2 index vertex
cost = get(edge_weight, g);
//Add directed arcs
for(int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++) {
if (i == j)
continue;
std::pair<Traits_vvd::edge_descriptor, bool> AE = add_edge(i, j, g);
assert(AE.second);
if (i == 0 && j == 1) cost[AE.first] = 1;
if (i == 0 && j == 2) cost[AE.first] = 2;
if (i == 1 && j == 0) cost[AE.first] = 1;
if (i == 1 && j == 2) cost[AE.first] = 2;
if (i == 2 && j == 0) cost[AE.first] = 1;
if (i == 2 && j == 1) cost[AE.first] = 2;
}
kruskal_minimum_spanning_tree(g, std::back_inserter(spanning_tree));
printf("MST Solution:\n");
for (std::vector < Edge >::iterator ei = spanning_tree.begin();
ei != spanning_tree.end(); ++ei) {
int fr = source(*ei, g);
int to = target(*ei, g);
double cst = cost[*ei];
printf("[%d %d]: %f \n", fr, to, cst);
}
getchar();
}
The code above generates the following bidirectional graph:
The output of the code is correctly:
MST Solution:
[0 1]: 1.000000
[2 0]: 1.000000
Is it the case that the document is not updated and in recent boost versions, the algorithm can actually work with directed graphs?
I'd simplify the code Live
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/kruskal_min_spanning_tree.hpp>
#include <iostream>
using Graph =
boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
boost::no_property,
boost::property<boost::edge_weight_t, double>>;
using Edge = Graph::edge_descriptor;
int main()
{
Graph g(3); // 0..2
/*auto [it, ok] =*/ add_edge(0, 1, {1}, g);
add_edge(0, 2, {2}, g);
add_edge(1, 0, {1}, g);
add_edge(1, 2, {2}, g);
add_edge(2, 0, {1}, g);
add_edge(2, 1, {2}, g);
auto cost = get(boost::edge_weight, g);
std::vector<Edge> spanning_tree;
kruskal_minimum_spanning_tree(g, std::back_inserter(spanning_tree));
std::cout << "MST Solution:\n";
for (auto e : spanning_tree) {
std::cout << e << ": " << cost[e] << "\n";
}
}
If you insist on a loop to insert edges: Live
for (auto [i, j, c] : { std::tuple //
{0, 1, 1.},
{0, 2, 2.},
{1, 0, 1.},
{1, 2, 2.},
{2, 0, 1.},
{2, 1, 2.},
})
{
if (!add_edge(i, j, {c}, g).second)
return 255;
}
The Question
If you don't meet the documented pre-conditions the output is unspecified. Unspecified doesn't mean it throws an exception (that would be specified). It might even accidentally (seem to) do the right thing.
The point is that the algorithm operates under the assumption that edges are - by definition - traversable in the reverse direction at the same cost. As soon as you deviate from that, the algorithm may give incorrect results. In fact, some algorithms might exhibit undefined behaviour (like, a Dijkstra with some weights negative might never complete).
You'd do better to
Either convert your graph to be undirected
satisfy the invariants of undirected graphs and verify that the algorithm works correctly for it
Use an algorithm for MDST (Minimum Directed Spanning Tree), see e.g. Finding a minimum spanning tree on a directed graph
Related
I have a vector of integers as follows: vector<int> vec {3, 4, 2, 1, 1, 3, 1}. Below code always returns the minimum element of 1 at index 3. How to make it randomly chose the minimum value of 1 from three locations [3, 4, 6] when same code is run multiple times?
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<int> vec {3, 4, 2, 1, 1, 3, 1};
auto it = min_element(vec.begin(), vec.end());
cout << *it << endl;
cout << "It is at a distance of: " << distance(vec.begin(), it) << endl;
return 0;
}
There are probably many ways to do this depending on your needs. Here's one:
#include <algorithm>
#include <iostream>
#include <random>
#include <vector>
int main() {
// a seeded random number generator
std::mt19937 prng(std::random_device{}());
std::vector<int> vec {3, 4, 2, 1, 1, 3, 1};
// get the min iterator to the first minimum element:
auto mit = std::min_element(vec.begin(), vec.end());
// collect the indices of all elements equal to the min element:
std::vector<std::size_t> ids;
for(auto fit = mit; fit != vec.end(); fit = std::find(fit + 1, vec.end(), *mit))
{
ids.push_back(std::distance(vec.begin(), fit));
}
// a distribution to select one of the indices in `ids`:
std::uniform_int_distribution<std::size_t> dist(0, ids.size()-1);
// print 10 randomly selected indices
for(int i = 0; i < 10; ++i) {
std::cout << ids[dist(prng)] << '\n';
}
}
Demo
Here's a single-pass variation based on selection sampling (though it could probably be made nicer), essentially being a case of Reservoir Sampling with a sample size of 1.
#include <iostream>
#include <random>
#include <vector>
#include <iterator>
template <typename T, typename URBG>
T rmin(T first, T last, URBG &g) {
if (first == last) return first;
T min = first;
using ud = std::uniform_int_distribution<std::size_t>;
using param_type = ud::param_type;
ud d;
std::size_t mincnt = 1;
++first;
while (first != last) {
if (*first < *min) {
/* Found new minimum. */
min = first;
mincnt = 1;
} else if (*first == *min) {
/* If equal to the minimum, select this with probability 1/mincnt + 1.
* Second has 1/2 chance to be selected, third has 1/3, etc. */
auto k = d(g, param_type{0, mincnt++});
if (!k) {
min = first;
}
}
++first;
}
return min;
}
int main() {
// a seeded random number generator
std::mt19937 prng(std::random_device{}());
std::vector<int> vec{3, 4, 2, 1, 1, 3, 1};
for (int i = 0; i < 10; i++) {
auto it = rmin(vec.begin(), vec.end(), prng);
std::cout << *it
<< " is at a distance of: " << std::distance(vec.begin(), it)
<< std::endl;
}
}
Demo of the above
This solution is random but likely does not give equal probability to all entries. However it avoids having to create new vectors and it is still O(N).
It works by randomly splitting the sequence (in logical sense) in two parts and taking the minimum of each. Then you return the minimum of the two parts.
As I said, it is likely not uniformly distributed but it is indeed still random.
#include <vector>
#include <algorithm>
#include <iostream>
#include <random>
template< typename T >
T minimum( T begin, T end ) {
std::size_t size = std::distance( begin, end );
if ( size<=1 ) return begin;
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<size_t> ds(1,size-1);
auto sep = begin + ds(gen);
auto it1 = std::min_element(begin, sep );
auto it2 = std::min_element(sep, end );
if ( *it1<*it2 ) return it1;
return it2;
}
int main() {
std::vector<int> vec {3, 4, 2, 1, 1, 3, 1};
for ( int j=0; j<10; ++j ) {
auto it = minimum( vec.begin(), vec.end() );
std::cout << *it << " is at a distance of: " << std::distance(vec.begin(), it) << std::endl;
}
return 0;
}
Produces
Program returned: 0
1 is at a distance of: 4
1 is at a distance of: 3
1 is at a distance of: 6
1 is at a distance of: 3
1 is at a distance of: 6
1 is at a distance of: 3
1 is at a distance of: 4
1 is at a distance of: 3
1 is at a distance of: 3
1 is at a distance of: 6
Godbolt: https://godbolt.org/z/3EhzdGndz
I want to print all vertices with their adjacent vertices. I found some examples online on how to do that, yet it won't work for me. I am getting the error, that the ++ operator cannot be used on ai. Also I think it needs to be vertex_idMap[*ai] and not vertex_idMap[ai] but this prompts an error. Does anyone know why this is wrong?
typedef adjacency_list<vecS, listS, directedS, VertexIDPorperty, EdgeWeight> Graph; //the type of g
graph_traits <Graph>::vertex_iterator i, end;
graph_traits <Graph>::adjacency_iterator ai, a_end;
for (boost::tie(i, end) = vertices(g); i != end; ++i) {
std::cout << vertex_idMap[*i];
for (; ai != a_end; ++ai) { //the ++ai seems to be wrong?
std::cout << vertex_idMap[ai];
if (boost::next(ai) != a_end)
std::cout << ", ";
}
std::cout << std::endl;
Observations:
Where's the rest of the code? It obviously depends on the types used.
ai and a_end aren't initialized (perhaps you didn't actually mean the code doesn't compile, and this was your whole problem)
vertex_idMap[ai] will not compile, as a vertex_iterator is not a valid vertex_descriptor
Here's a fixed example with the missing bits imagined:
Live On Coliru
#include <boost/graph/adjacency_list.hpp>
#include <iostream>
using VertexIDPorperty = boost::property<boost::vertex_index_t, int>;
using EdgeWeight = boost::property<boost::edge_weight_t, double>;
typedef boost::adjacency_list<boost::vecS, boost::listS, boost::directedS, VertexIDPorperty, EdgeWeight> Graph;
Graph sample();
int main() {
Graph g = sample();
auto vertex_idMap = get(boost::vertex_index, g);
boost::graph_traits <Graph>::vertex_iterator i, end;
boost::graph_traits <Graph>::adjacency_iterator ai, a_end;
for (boost::tie(i, end) = vertices(g); i != end; ++i) {
std::cout << vertex_idMap[*i] << ": ";
for (boost::tie(ai, a_end) = adjacent_vertices(*i, g); ai != a_end; ++ai) {
std::cout << vertex_idMap[*ai];
if (boost::next(ai) != a_end)
std::cout << ", ";
}
std::cout << std::endl;
}
}
Implementing sample() to create a random graph:
#include <boost/graph/random.hpp>
#include <random>
Graph sample() {
Graph g;
std::mt19937 prng { std::random_device{}() };
generate_random_graph(g, 10, 20, prng);
int id = 0;
for (auto vd : boost::make_iterator_range(vertices(g))) {
put(boost::vertex_index, g, vd, ++id);
}
return g;
}
It prints something like:
1: 9, 9, 4
2: 6
3:
4:
5: 9, 9, 8, 9
6: 9, 3, 1
7: 2, 10
8: 6
9: 8
10: 7, 3, 8, 1, 4
Out Of The Box
Printing a graph can be done simpler:
#include <boost/graph/graph_utility.hpp>
// ...
int main() {
print_graph(sample());
}
Live On Coliru
1 -->
2 --> 3 10 9 6 6 10
3 --> 8
4 -->
5 --> 4
6 --> 1 5 8
7 --> 4 9 2 2 1
8 --> 6
9 --> 5 7
10 --> 7
I'm writing an operation to find the lowest missing element of a vector, V = 1..N + 1. This has to be performed in O(N) time complexity.
Solution One:
std::vector<int> A {3,4,1,4,6,7};
int main()
{
int max_el = *std::max_element(A.begin(), A.end()); //Find max element
std::vector<int> V(max_el);
std::iota(V.begin(), V.end(), 1) //Populate V with all int's up to max element
for(unsigned into i {0}; i < A.size(); i++)
{
int index = A[i] - 1;
if(A[i] == V[index]) //Search V in O(1)
{
V[index] = max_el; //Set each to max_el, leaving the missing int
}
}
return *std::min_element(V.begin(), V.end()); //Find missing int as its the lowest (hasn't been set to max_el)
}
//Output: 2
This works completely fine.
However, I'm now trying to get this to work with vector containing negative int's.
Solution Two:
My logic is to take the same approach, however 'weight' the indexes given the size of the vector and the number of negative int's in the vector:
std::vector<int> A {-1, -4, -2, 0, 3, 2, 1}
int main()
{
int max_el = *std::max_element(A.begin(), A.end());
int min_el = *std::min_element(A.begin(), A.end());
int min_el_abs = abs(min_el); //Convert min element to absolute
int total = min_el_abs + max_el;
std::vector<int> V(total + 1);
std::iota(V.begin(), V.end(), min_el);
int index;
//Find amount of negative int's
int first_pos;
for(unsigned int i {0}; i < A.size(); i++)
{
if(A[i] >= 0) {first_pos = i; break;}
}
for(unsigned int i {0}; i < A.size(); i++)
{
if(A[i] <= 0) //If negative
{
index = (A.size() - first_pos) - abs(A[i]);
} else
{
index = (A[i] + 1) + first_pos;
}
if(A[i] == V[index])
{
V[index] = 0;
}
}
return *std::min_element(V.begin(), V.end());
}
//Output: -3
Solution Two fails to compare the values of the two vectors (A and V), as calculating the index with the above methods with a positive int doesn't work.
1) How can I get my Solution 2 to work with unordered vector's of negative int's?
2) How can I edit my Solution 2 to work with vectors of positive as well as vectors with negative int's?
Your first solution seems O(max(N,M)), where I consider N the number of elements in vector A and M the size of vector V (or max(Ai)), but you are looping through both vectors multiple times (with std::min_element, std::max_element, the for loop, the allocation of V and std::iota too).
Besides, once corrected a couple of typos (a missing ; and an into instead of int), your program returns the value found... from main(), which is a bit odd.
Your first algorithm always searches for the lowest missing value in the range [1, max value in A], but it can be generalized to find the lowest missing element in the range [min(Ai), max(Ai)], even for negative numbers.
My approach is similar to that of L.Senioins, but I've used different library functions trying to minimize the number of loops.
#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
template <class ForwardIt>
typename std::iterator_traits<ForwardIt>::value_type
lowest_missing(ForwardIt first, ForwardIt last)
{
if ( first == last )
throw std::string {"The range is empty"};
// find both min and max element with one function
auto result = std::minmax_element(first, last);
// range is always > 0
auto range = *result.second - *result.first + 1;
if ( range < 2 )
throw std::string {"Min equals max, so there are no missing elements"};
std::vector<bool> vb(range); // the initial value of all elements is false
for (auto i = first; i != last; ++i)
vb[*i - *result.first] = true;
// search the first false
auto pos = std::find(vb.cbegin(), vb.cend(), false);
if ( pos == vb.cend() ) // all the elements are true
throw std::string {"There are no missing elements"};
return std::distance(vb.cbegin(), pos) + *result.first;
}
template <class ForwardIt>
void show_the_first_missing_element(ForwardIt first, ForwardIt last)
{
try
{
std::cout << lowest_missing(first, last) << '\n';
}
catch(const std::string &msg)
{
std::cout << msg << '\n';
}
}
int main() {
std::vector<int> a { 1, 8, 9, 6, 2, 5, 3, 0 };
show_the_first_missing_element(a.cbegin(), a.cend());
std::vector<int> b { -1, -4, 8, 1, -3, -2, 10, 0 };
show_the_first_missing_element(b.cbegin(), b.cend());
show_the_first_missing_element(b.cbegin() + b.size() / 2, b.cend());
std::vector<int> c { -2, -1, 0, 1, 2, 3 };
show_the_first_missing_element(c.cbegin(), c.cend());
std::vector<int> d { 3, 3, 3 };
show_the_first_missing_element(d.cbegin(), d.cend());
std::vector<int> e;
show_the_first_missing_element(e.cbegin(), e.cend());
return 0;
}
The results outputted for my test cases are:
4
2
-1
There are no missing elements
Min equals max, so there are no missing elements
The range is empty
My solution is to make a bool vector (or char vector just to avoid compilation warnings about casting to bool) which has the size of all possible elements. All elements are initialized to 0 and later are assigned to 1 which indicates that the element is not missing. All you need to do then is to find an index of the first 0 element which is the lowest missing element.
#include <vector>
#include <algorithm>
#include <iostream>
std::vector<int> A{ -1, 0, 11, 1, 10, -5 };
int main() {
if (A.size() > 1) {
int max_el = *std::max_element(A.begin(), A.end());
int min_el = *std::min_element(A.begin(), A.end());
int range = abs(max_el - min_el) + 1;
std::vector<int> V(range, 0);
for (size_t i = 0; i < A.size(); i++)
V[A[i] - min_el] = 1;
if (*std::min_element(V.begin(), V.end()) == 0)
std::cout << std::distance(V.begin(), std::find(V.begin(), V.end(), 0)) + min_el;
else
std::cout << "There are no missing elements" << std::endl;
}
else
std::cout << "There are no missing elements" << std::endl;
std::cin.get();
}
I'm going to try give my own question an answer, after spending sometime thinking about this:
int main()
{
std::vector<int> A {-3, -1, 0, 1, 3, 4};
auto relative_pos = std::minmax_elment(A.begin(), A.end());
std::vector<bool> Litmus( *(relative_pos.second) - *(relative_pos.first), false); //Create vector of size max val - min val)
auto lowest_val = *(relative_pos.first);
for(auto x : A)
{
Litmus[i - lowest_val] = true;
}
auto pos = std::find(Litmus.begin(), Litmus.end(), false); //Find the first occurring false value
std::cout<< (pos - Litmus.begin()) + lower<<std::endl; //Print the val in A relative to false value in Litmus
}
This solution works with negative numbers and is linear.
#include <vector>
#include <iostream>
#include <string>
#include <algorithm>
#include <numeric>
int solution(vector<int> &A) {
std::vector<int>::iterator it = std::max_element(A.begin(),A.end());
try
{
sort(A.begin(),A.end());
std::vector<int>::iterator it = std::unique(A.begin(),A.end());
A.resize(std::distance(A.begin(),it));
for(int i = 0, j = 1; i < A.size(); i++)
{
if( A[i] != j)
{
return j;
}
j++;
}
}
catch(exception &e)
{
std::cout<<e.what()<<std::endl;
}
return ++(*it);
}
Hi I am pretty new to the Boost libraries. I want to build a graph from a square two dimensional map that will be used for a star algorithm (the map is an array with 1s and 0s for both wall and normal terrain).
The graph should be undirected and change with the size of the map. Each node has 8 edges (except for sides of the map).
I've gone through a few examples but I don't understand the procedure for building graphs of this size since most examples look like this (look bellow) in the boost graph library documentation.
Any help or ideas will be really appreciated
#include <iostream> // for std::cout
#include <utility> // for std::pair
#include <algorithm> // for std::for_each
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
using namespace boost;
int main(int,char*[])
{
// create a typedef for the Graph type
typedef adjacency_list<vecS, vecS, bidirectionalS> Graph;
// Make convenient labels for the vertices
enum { A, B, C, D, E, N };
const int num_vertices = N;
const char* name = "ABCDE";
// writing out the edges in the graph
typedef std::pair<int, int> Edge;
Edge edge_array[] =
{ Edge(A,B), Edge(A,D), Edge(C,A), Edge(D,C),
Edge(C,E), Edge(B,D), Edge(D,E) };
const int num_edges = sizeof(edge_array)/sizeof(edge_array[0]);
// declare a graph object
Graph g(num_vertices);
// add the edges to the graph object
for (int i = 0; i < num_edges; ++i){
add_edge(edge_array[i].first, edge_array[i].second, g);
}
return 0;
}
On second reading of the question it seems like your question is simply how to add nodes and edges.
Here's a start that queries for the number of rows/columns and creates the square "grid". I use a nodes matrix on the side to have easy lookup from (x,y) in the grid to the vertex descriptor in the graph.
Live On Coliru
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_utility.hpp>
#include <iostream>
using namespace boost;
struct Point {
int x, y;
friend std::ostream& operator<<(std::ostream& os, Point p) {
return os << "[" << p.x << "," << p.y << "]";
}
};
int main() {
using std::vector;
using Graph = adjacency_list<setS, vecS, undirectedS, Point>;
using vertex_descriptor = Graph::vertex_descriptor;
Graph lattuce;
int num_rows;
if (!(std::cin >> num_rows && num_rows > 0))
return 255;
vector<vector<vertex_descriptor> > nodes(num_rows, vector<vertex_descriptor>(num_rows));
for (auto i = 0; i < num_rows; ++i)
for (auto j = 0; j < num_rows; ++j)
nodes[i][j] = add_vertex(Point{i,j}, lattuce);
auto is_valid = [num_rows](Point p) { return (p.x >= 0 && p.x < num_rows) &&
(p.y >= 0 && p.y < num_rows); };
for (auto vd : make_iterator_range(vertices(lattuce))) {
auto p = lattuce[vd];
for (Point neighbour : {
Point { p.x - 1, p.y - 1 }, Point { p.x - 1, p.y + 0 }, Point { p.x - 1, p.y + 1 },
Point { p.x + 0, p.y - 1 }, Point { p.x + 0, p.y + 1 },
Point { p.x + 1, p.y - 1 }, Point { p.x + 1, p.y + 0 }, Point { p.x + 1, p.y + 1 },
})
{
if (is_valid(neighbour))
add_edge(nodes[neighbour.x][neighbour.y], vd, lattuce);
};
}
print_graph(lattuce, get(vertex_bundle, lattuce));
}
Prints, e.g. for input 3:
[0,0] <--> [0,1] [1,0] [1,1]
[0,1] <--> [0,0] [0,2] [1,0] [1,1] [1,2]
[0,2] <--> [0,1] [1,1] [1,2]
[1,0] <--> [0,0] [0,1] [1,1] [2,0] [2,1]
[1,1] <--> [0,0] [0,1] [0,2] [1,0] [1,2] [2,0] [2,1] [2,2]
[1,2] <--> [0,1] [0,2] [1,1] [2,1] [2,2]
[2,0] <--> [1,0] [1,1] [2,1]
[2,1] <--> [1,0] [1,1] [1,2] [2,0] [2,2]
[2,2] <--> [1,1] [1,2] [2,1]
I was trying to save some space by using a hashmap to represent a graph instead of adjacency matrix, I ran the same snippet using adjacency matrix, and everything worked fine, But as soon as I changed the data structure to a hashmap, it ran into in infinite loop, The infinite loop is because of the bsf function defined which returns a boolean value and more specifically the error is in line : if ((!visited[v]) && (rGraph[make_pair(u, v)] > 0)) somehow this if condition is not working fine while I represent the rGraph as a hashmap.
I would also like to know if using a hashmap to represent the graph is a preferred way ?
Here is the attached code:
bool bfs(map<pair<int, int>, int> rGraph, int s, int t, int parent[])
{
// Create a visited array and mark all vertices as not visited
bool visited[V];
memset(visited, 0, sizeof(visited));
// Create a queue, enqueue source vertex and mark source vertex
// as visited
queue <int> q;
q.push(s);
visited[s] = true;
parent[s] = -1;
// Standard BFS Loop
while (!q.empty())
{
int u = q.front();
q.pop();
for (int v=0; v<V; v++)
{
cout << "Value of graph at: " <<u << " , " << v << " : " << rGraph[make_pair(u, v)] << "\n";
//cout << "!visited[v] : " << (!visited[v]) << "rGraph[u][v] : " << rGraph[make_pair(u, v)] << "\n";
cout << "if condition : " << ((!visited[v]) && (rGraph[make_pair(u, v)] > 0)) << "\n";
if ((!visited[v]) && (rGraph[make_pair(u, v)] > 0))
{
q.push(v);
parent[v] = u;
visited[v] = true;
}
}
}
// If we reached sink in BFS starting from source, then return
// true, else false
return (visited[t] == true);
}
// Returns tne maximum flow from s to t in the given graph
int fordFulkerson(map<pair<int, int> , int> graph , int s, int t)
{
int u, v;
// Create a residual graph and fill the residual graph with
// given capacities in the original graph as residual capacities
// in residual graph
map<pair<int, int>, int>rGraph; // Residual graph where rGraph[i][j] indicates
// residual capacity of edge from i to j (if there
// is an edge. If rGraph[i][j] is 0, then there is not)
for (u = 0; u < V; u++){
for (v = 0; v < V; v++){
rGraph[make_pair(u, v)] = graph[make_pair(u, v)];
}
}
int parent[V]; // This array is filled by BFS and to store path
int max_flow = 0; // There is no flow initially
// Augment the flow while tere is path from source to sink
while (bfs(rGraph, s, t, parent))
{
// Find minimum residual capacity of the edhes along the
// path filled by BFS. Or we can say find the maximum flow
// through the path found.
int path_flow = INT_MAX;
for (v=t; v!=s; v=parent[v])
{
u = parent[v];
path_flow = min(path_flow, int(rGraph[make_pair(u, v)]));
}
// update residual capacities of the edges and reverse edges
// along the path
for (v=t; v != s; v=parent[v])
{
u = parent[v];
rGraph[make_pair(u, v)] -= path_flow;
rGraph[make_pair(u, v)] += path_flow;
}
// Add path flow to overall flow
max_flow += path_flow;
}
// Return the overall flow
return max_flow;
}
int main(){
map< pair<int, int>, int > graph;
graph[make_pair(0, 1)] = 16;
graph[make_pair(0, 2)] = 13;
graph[make_pair(1, 2)] = 10;
graph[make_pair(1, 3)] = 12;
graph[make_pair(2, 1)] = 4;
graph[make_pair(2, 4)] = 14;
graph[make_pair(3, 2)] = 9;
graph[make_pair(3, 5)] = 20;
graph[make_pair(4, 3)] = 7;
graph[make_pair(4, 5)] = 4;*/
cout << "The maximum possible flow is " << fordFulkerson(graph, 0, 5) << "\n";
return 0;
}
And the adjacency matrix looks like :
int graph[V][V] = { {0, 16, 13, 0, 0, 0},
{0, 0, 10, 12, 0, 0},
{0, 4, 0, 0, 14, 0},
{0, 0, 9, 0, 0, 20},
{0, 0, 0, 7, 0, 4},
{0, 0, 0, 0, 0, 0}};
First, just by looking at your code - you are not using hashmap - you are using map (read: red-black tree in most implementations). Equivalent of "hashmap" would be unordered_map. However, if you want to save memory - you have chosen the right container (unordered_map may consume more memory than map - unordered_map (hashmap) requires continuous region of memory for buckets: and of course all buckets are never occupied).
And now to problems:
When you do rGraph[make_pair(u, v)] you are potentially creating a new element in your map. Indexing operator returns (see cppreference):
reference to an existing element pointed by the index make_pair(u, v)
if the element pointed by make_pair(u, v) does not exist - it creates a new element under that index and returns you the reference to that new element.
If you want to check whether an element exists in the map / unordered_map you have to use the find method:
auto p = make_pair(u, v)];
auto iter = rGraph.find(p);
if(iter != rGraph.end())
{//element 'rGraph[p]' exists
}
else
{//element 'rGraph[p]' does not exist
}
You can also combine (potentially) inserting new element with checking whether the new element was actually created - this is usually more efficient than two separate insert and find (see cppreference):
auto p = make_pair(u, v)];
auto res = rGraph.insert(make_pair(p,1)); //insert value '1'
if(res.second)
{//new element was inserted
}
else
{//element already existed
}
//here res.first is an iterator pointing to the element rGraph[p] - newly inserted or not
You should use the count or find methods to check existence of items in the map, instead of the operator [] because it constructs a new item if it doesn't exist. So change
rGraph[make_pair(u, v)]>0
with
rGraph.count(make_pair(u, v))>0
Also, I might suggest passing any large object (such as the map) by reference. Also, as mentioned here, you can use "unordered_map" which is a hash table, instead of "map" which is a tree, since you don't need the map to be ordered.