#include <iostream> //std::cin,cout,ios_base
#include <vector> //std::vector
#include <tuple> //std::tie
#include <limits.h> //INT_MAX (no `std::')

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_traits.hpp>

#include <boost/graph/push_relabel_max_flow.hpp>

using namespace boost;

struct VertexProperties{

};

struct EdgeProperties{
	int id;
	int capacity;
	int residual_capacity;
};

typedef boost::adjacency_list<vecS,vecS,directedS,VertexProperties,EdgeProperties> Graph;
typedef boost::graph_traits<Graph> Traits;
typedef Traits::vertex_descriptor Vertex;
typedef Traits::edge_descriptor Edge;

void do_add_edge(int& next_id, const Vertex& a, const Vertex& b, const int c, Graph& g,std::map<Edge,Edge>& reverse_edge_of);

int main(int arc, char* argv[]){
	std::ios_base::sync_with_stdio(false);
	
	int n = 3; //nof vertices ( >2)
	
	Graph g(n);
		
	Vertex s = vertex(n-2,g); //source
	Vertex t = vertex(n-1,g); //sink
	
	Vertex u = vertex(0,g);
	
	std::map<Edge,Edge> reverse_edge_map;
	int next_id = 0;
	
	do_add_edge(next_id,s,u,3,g,reverse_edge_map);
	do_add_edge(next_id,u,t,1,g,reverse_edge_map);
	
	std::vector<int> rescap(num_edges(g));
	
	//why doesn't this work?
	/*int maxflow = push_relabel_max_flow(
		g,
		s,
		t,
		capacity_map(get(&EdgeProperties::capacity,g))
		.residual_capacity_map(get(&EdgeProperties::residual_capacity,g))
		.reverse_edge_map(make_assoc_property_map(reverse_edge_map))
		.vertex_index_map(get(vertex_index,g))
	);*/
	
	//this does work
	int maxflow = push_relabel_max_flow(
		g,
		s,
		t,
		get(&EdgeProperties::capacity,g),
		get(&EdgeProperties::residual_capacity,g),
		make_assoc_property_map(reverse_edge_map),
		get(vertex_index,g)
	);
	
	std::cout << "maxflow = " << maxflow << "\n";

	return 0;
}

void do_add_edge(int& next_id, const Vertex& a, const Vertex& b, const int c, Graph& g,std::map<Edge,Edge>& reverse_edge_of){
	Edge e,re; bool success;

	std::tie(e,success) = add_edge(a,b,g);
	g[e].id = next_id;
	g[e].capacity = c;
	g[e].residual_capacity = c;

	//reverse edge
	std::tie(re,success) = add_edge(b,a,g);
	g[re].id = next_id + 1;
	g[re].capacity = 0;
	g[re].residual_capacity = 0;

	reverse_edge_of[e] = re;
	reverse_edge_of[re] = e;

	next_id += 2;
}