Advertisement
Guest User

Untitled

a guest
Jun 26th, 2017
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.44 KB | None | 0 0
  1. //////////////////////////////////////////////////////////////////////////////
  2. /// @file       NetworkFlow.h
  3. /// @author     Benjamin Fedder Jensen (bfje@itu.dk)
  4. /// @brief      Flow Behind Enemy Lines
  5. //              Implements the Ford-Fulkerson Algorithm
  6. //////////////////////////////////////////////////////////////////////////////
  7. #ifndef NETWORKFLOW_H
  8. #define NETWORKFLOW_H
  9.  
  10. #include <iostream>
  11. #include <string>
  12. #include <sstream>
  13. #include <fstream>
  14. #include <list>
  15. #include <vector>
  16. #include <limits>
  17. #include <queue>
  18. #include <set>
  19. #include <unordered_map>
  20.  
  21. namespace algorithms {
  22.  
  23.     enum EdgeType { FORWARD, BACKWARD };
  24.     struct Node;    // forward declaration
  25.  
  26.     struct Edge {
  27.     public:
  28.         Node&           u;  // source
  29.         Node&           v;  // destination
  30.         int             c;  // capacity
  31.         int             f;  // flow
  32.         Edge(Node& u, Node& v, int c) : u(u), v(v), c(c), f(0) {};
  33.     };
  34.  
  35.     struct ResidualEdge {   // residual edge - derives all from its edge parent e
  36.         Edge&           e;  // edge it belongs to
  37.         EdgeType        t;  // type of edge - determines capacity & direction in graph
  38.         int capacity(void)      { return (t == FORWARD) ? e.c - e.f : e.f; }    // residual capacity
  39.         Node&           u(void) { return (t == FORWARD) ? e.u : e.v; }          // source
  40.         Node&           v(void) { return (t == FORWARD) ? e.v : e.u; }          // destination
  41.         ResidualEdge(Edge& e, EdgeType t) : e(e), t(t) {};
  42.     };
  43.  
  44.     struct Node {
  45.         std::wstring     n;         // name
  46.         std::list<Edge>  o;         // outgoing edges
  47.         std::list<ResidualEdge> r;  // residual edges
  48.         Node(std::wstring n) : n(n) {};
  49.     };
  50.  
  51.     typedef std::list<ResidualEdge*> path;
  52.  
  53.     class NetworkFlow {
  54.         // Append result set to output stream
  55.         friend std::wostream& operator<<(std::wostream& os, NetworkFlow& a);
  56.     private:
  57.         std::vector<Node>   graph; // Both graph & residual graph
  58.     public:
  59.         NetworkFlow&    Load(const std::wstring&);          // Load data set
  60.         int             Execute(void);                      // Execute algorithm
  61.     private:
  62.         void            Augment(path&);                     // Augmenting path
  63.         int             BottleNeck(path&);                  // Bottleneck
  64.         path            BreadthFirstSearch(Node&, Node&, std::set<Edge*>* = NULL);  // BFS search, returns layer
  65.     };
  66.  
  67.     NetworkFlow& NetworkFlow::Load(const std::wstring& data) {
  68.         std::wcout << L"algorithms::NetworkFlow::Load : Opening file \"" << data << L"\"." << std::endl;
  69.         std::wifstream file;
  70.         file.open(data, std::wifstream::in);
  71.         if (!file.is_open()) throw std::exception("algorithms::NetworkFlow::Load : Could not open file.");
  72.         std::wstring ILine;
  73.         std::getline(file, ILine);
  74.         int n = _wtoi(ILine.c_str());
  75.         for (int i = 0; i < n && std::getline(file, ILine); i++) graph.push_back(Node(ILine));
  76.         std::getline(file, ILine);
  77.         int m = _wtoi(ILine.c_str());
  78.         for (int i = 0; i < m && std::getline(file, ILine); i++) {
  79.             std::wistringstream IStream(ILine);
  80.             int u, v, c;
  81.             IStream >> u >> v >> c;
  82.             if (c < 0) c = std::numeric_limits<int>::max();
  83.             graph[u].o.push_back(Edge(graph[u], graph[v], c));
  84.             graph[u].r.push_back(ResidualEdge(graph[u].o.back(), FORWARD));
  85.             graph[v].r.push_back(ResidualEdge(graph[u].o.back(), BACKWARD));
  86.             graph[v].o.push_back(Edge(graph[v], graph[u], c));
  87.             graph[v].r.push_back(ResidualEdge(graph[v].o.back(), FORWARD));
  88.             graph[u].r.push_back(ResidualEdge(graph[v].o.back(), BACKWARD));
  89.         }
  90.         file.close();
  91.         return *this;
  92.     }
  93.  
  94.     int NetworkFlow::Execute(void) {
  95.         Node& s = graph.front();    // source
  96.         Node& t = graph.back();     // sink
  97.         path p;                     // path to sink
  98.         int sum = 0;
  99.         while(!(p = BreadthFirstSearch(s, t)).empty()) Augment(p);
  100.         std::list<Edge>::iterator i;
  101.         for (i = graph.front().o.begin(); i != graph.front().o.end(); i++) sum += (*i).f;
  102.         return sum;
  103.     }
  104.  
  105.     void NetworkFlow::Augment(path& p) {
  106.         int b = BottleNeck(p);
  107.         for (path::iterator i = p.begin(); i != p.end(); i++) {
  108.             if ((*i)->t == FORWARD) (*i)->e.f += b;
  109.             else                    (*i)->e.f -= b;
  110.         }
  111.     }
  112.  
  113.     int NetworkFlow::BottleNeck(path& p) {
  114.         int b = std::numeric_limits<int>::max();
  115.         for (path::iterator i = p.begin(); i != p.end(); i++) if ((*i)->capacity() <= b) b = (*i)->capacity();
  116.         return b;
  117.     }
  118.  
  119.     path NetworkFlow::BreadthFirstSearch(Node& s, Node& t, std::set<Edge*>* bottleneck) {
  120.         std::queue<Node*> queue;    // FIFO
  121.         std::set<Node*> closed;     // closed set - visited nodes
  122.         path p;                     // found path as a list
  123.         std::unordered_map<Node*, ResidualEdge*> prev;  // previous nodes - encodes path
  124.         queue.push(&s);
  125.         closed.insert(&s);
  126.         while (!queue.empty()) {
  127.             Node* n = queue.front();
  128.             queue.pop();
  129.             if (n == &t) break;
  130.             std::list<ResidualEdge>::iterator i;
  131.             for (i = n->r.begin(); i != n->r.end(); i++) {
  132.                 if (closed.find(&(i->v())) != closed.end()) continue; // is in closed set
  133.                 if (i->capacity() < 1) {
  134.                     if (bottleneck) bottleneck->insert(&(*i).e);
  135.                     continue; // has no capacity
  136.                 }
  137.                 queue.push(&(i->v()));
  138.                 closed.insert(&(i->v()));
  139.                 prev[&(i->v())] = &(*i);
  140.             }
  141.         }
  142.         if (prev.find(&t) == prev.end()) return p; // t was not reached
  143.         for(Node* n = &t; n != &s; n = &(prev[n]->u())) p.push_front(prev[n]);
  144.         return p; // t was reached - return path
  145.     }
  146.  
  147.     inline std::wostream& operator<<(std::wostream& os, NetworkFlow& a) {
  148.         Node& s = a.graph.front();  // source
  149.         Node& t = a.graph.back();   // sink
  150.         std::set<Edge*> bottleneck; // bottleneck edges
  151.         a.BreadthFirstSearch(s, t, &bottleneck);
  152.         std::set<Edge*>::iterator i;
  153.         for (i = bottleneck.begin(); i != bottleneck.end(); i++) {
  154.             if ((*i)->f == (*i)->c) // only show those leading from A to B - for each edge there is an edge from B to A with 0 flow
  155.                 os << (*i)->u.n << L" --> " << (*i)->v.n << ", flow: " << (*i)->f << ", capacity: " << (*i)->c << "\n";
  156.         }
  157.         return os ;
  158.     }
  159.  
  160. }
  161.  
  162. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement