// -*- c++ -*-
#include <iostream>
#include <fstream>

#include <list_graph.h>
#include <smart_graph.h>
#include <dimacs.h>
#include <edmonds_karp.h>
#include <time_measure.h>
#include <graph_wrapper.h>

class CM {
public:
  template<typename T> int get(T) const {return 1;}
};

using namespace lemon;

// Use a DIMACS max flow file as stdin.
// read_dimacs_demo < dimacs_max_flow_file


//   struct Ize {
//   };
  
//   struct Mize {
//     Ize bumm;
//   };

//   template <typename B>
//     class Huha {
//     public:
//       int u;
//       B brr;
//     };


int main(int, char **) {

  typedef ListGraph MutableGraph;

  //typedef SmartGraph Graph;
  typedef ListGraph Graph;
  typedef Graph::Node Node;
  typedef Graph::EdgeIt EdgeIt;


//   Mize mize[10];
//   Mize bize[0];
//   Mize zize;
//   typedef Mize Tize[0];

//   std::cout << &zize << " " << sizeof(mize) << sizeof(Tize) << std::endl;
//   std::cout << sizeof(bize) << std::endl;


//   Huha<Tize> k;
//   std::cout << sizeof(k) << std::endl;


//   struct Bumm {
//     //int a;
//     bool b;
//   };

//   std::cout << sizeof(Bumm) << std::endl;


  Graph G;
  Node s, t;
  Graph::EdgeMap<int> cap(G);
  readDimacsMaxFlow(std::cin, G, s, t, cap);

//   typedef TrivGraphWrapper<Graph> TGW;
//   TGW gw(G);
//   TGW::NodeIt sw;
//   gw./*getF*/first(sw);
//   std::cout << "p1:" << gw.nodeNum() << std::endl;
//   gw.erase(sw);
//   std::cout << "p2:" << gw.nodeNum() << std::endl;

//   typedef const Graph cLG;
//   typedef TrivGraphWrapper<const cLG> CTGW;
//   CTGW cgw(G);
//   CTGW::NodeIt csw;
//   cgw./*getF*/first(csw);
//   std::cout << "p1:" << cgw.nodeNum() << std::endl;
//   //cgw.erase(csw);
//   std::cout << "p2:" << cgw.nodeNum() << std::endl;


  {
    typedef TrivGraphWrapper<const Graph> GW;
    GW gw(G);
    std::cout << "edmonds karp demo (physical blocking flow augmentation)..." << std::endl;
    GW::EdgeMap<int> flow(gw); //0 flow

    Timer ts;
    ts.reset();

    typedef GW::EdgeMapWrapper< Graph::EdgeMap<int>, int > EMW;
    EMW cw(cap);
    MaxFlow<GW, int, GW::EdgeMap<int>, EMW > max_flow_test(gw, s, t, flow, cw);
    int i=0;
    while (max_flow_test.augmentOnBlockingFlow<MutableGraph>()) { 
//     for(EdgeIt e=G.template first<EdgeIt>(); e.valid(); ++e) { 
//       std::cout<<"("<<G.source(e)<< "-"<<flow.get(e)<<"->"<<G.target(e)<<") ";
//     }
//     std::cout<<std::endl;
      ++i; 
    }

//   std::cout << "maximum flow: "<< std::endl;
//   for(EdgeIt e=G.first<EdgeIt>(); e.valid(); ++e) { 
//     std::cout<<"("<<G.source(e)<< "-"<<flow.get(e)<<"->"<<G.target(e)<<") ";
//   }
//   std::cout<<std::endl;
    std::cout << "elapsed time: " << ts << std::endl;
    std::cout << "number of augmentation phases: " << i << std::endl; 
    std::cout << "flow value: "<< max_flow_test.flowValue() << std::endl;
  }

  {
    typedef TrivGraphWrapper<const Graph> GW;
    GW gw(G);
    std::cout << "edmonds karp demo (physical blocking flow 1 augmentation)..." << std::endl;
    GW::EdgeMap<int> flow(gw); //0 flow

    Timer ts;
    ts.reset();

    typedef GW::EdgeMapWrapper< Graph::EdgeMap<int>, int > EMW;
    EMW cw(cap);
    MaxFlow<GW, int, GW::EdgeMap<int>, EMW > max_flow_test(gw, s, t, flow, cw);
    int i=0;
    while (max_flow_test.augmentOnBlockingFlow1<MutableGraph>()) { 
//     for(EdgeIt e=G.template first<EdgeIt>(); e.valid(); ++e) { 
//       std::cout<<"("<<G.source(e)<< "-"<<flow.get(e)<<"->"<<G.target(e)<<") ";
//     }
//     std::cout<<std::endl;
      ++i; 
    }

//   std::cout << "maximum flow: "<< std::endl;
//   for(EdgeIt e=G.first<EdgeIt>(); e.valid(); ++e) { 
//     std::cout<<"("<<G.source(e)<< "-"<<flow.get(e)<<"->"<<G.target(e)<<") ";
//   }
//   std::cout<<std::endl;
    std::cout << "elapsed time: " << ts << std::endl;
    std::cout << "number of augmentation phases: " << i << std::endl; 
    std::cout << "flow value: "<< max_flow_test.flowValue() << std::endl;
  }

  {
    typedef TrivGraphWrapper<const Graph> GW;
    GW gw(G);
    std::cout << "edmonds karp demo (on-the-fly blocking flow augmentation)..." << std::endl;
    GW::EdgeMap<int> flow(gw); //0 flow

    Timer ts;
    ts.reset();

    typedef GW::EdgeMapWrapper< Graph::EdgeMap<int>, int > EMW;
    EMW cw(cap);
    MaxFlow<GW, int, GW::EdgeMap<int>, EMW > max_flow_test(gw, s, t, flow, cw);
    int i=0;
    while (max_flow_test.augmentOnBlockingFlow2()) { 
//     for(EdgeIt e=G.template first<EdgeIt>(); e.valid(); ++e) { 
//       std::cout<<"("<<G.source(e)<< "-"<<flow.get(e)<<"->"<<G.target(e)<<") ";
//     }
//     std::cout<<std::endl;
      ++i; 
    }

//   std::cout << "maximum flow: "<< std::endl;
//   for(EdgeIt e=G.first<EdgeIt>(); e.valid(); ++e) { 
//     std::cout<<"("<<G.source(e)<< "-"<<flow.get(e)<<"->"<<G.target(e)<<") ";
//   }
//   std::cout<<std::endl;
    std::cout << "elapsed time: " << ts << std::endl;
    std::cout << "number of augmentation phases: " << i << std::endl; 
    std::cout << "flow value: "<< max_flow_test.flowValue() << std::endl;
  }

  {
    typedef TrivGraphWrapper<const Graph> GW;
    GW gw(G);
    std::cout << "edmonds karp demo (on-the-fly shortest path augmentation)..." << std::endl;
    GW::EdgeMap<int> flow(gw); //0 flow

    Timer ts;
    ts.reset();

    typedef GW::EdgeMapWrapper< Graph::EdgeMap<int>, int > EMW;
    EMW cw(cap);
    MaxFlow<GW, int, GW::EdgeMap<int>, EMW> max_flow_test(gw, s, t, flow, cw);
    int i=0;
    while (max_flow_test.augmentOnShortestPath()) { 
//     for(EdgeIt e=G.template first<EdgeIt>(); e.valid(); ++e) { 
//       std::cout<<"("<<G.source(e)<< "-"<<flow.get(e)<<"->"<<G.target(e)<<") ";
//     }
//     std::cout<<std::endl;
      ++i; 
    }

//   std::cout << "maximum flow: "<< std::endl;
//   for(EdgeIt e=G.first<EdgeIt>(); e.valid(); ++e) { 
//     std::cout<<"("<<G.source(e)<< "-"<<flow.get(e)<<"->"<<G.target(e)<<") ";
//   }
//   std::cout<<std::endl;
    std::cout << "elapsed time: " << ts << std::endl;
    std::cout << "number of augmentation phases: " << i << std::endl; 
    std::cout << "flow value: "<< max_flow_test.flowValue() << std::endl;
  }


  return 0;
}
