#include #include #include #include #include #include #include using namespace std; class Node { public: string name; // The node's name vector adj; // The node's adjacency list in the residual graph. int visited; // A visited field for depth-first search. }; class Edge { public: void Print() const; // This prints the edge's name and residual flow. string name; // The edge's name (to store in the edge map). Node *n1; // The "from" node Node *n2; // The "to" node Edge *reverse; // The reverse edge, for processing the residual graph int original; // The original edge capacity. int residual; // The edge capacity in the residual graph. }; class Graph { public: Graph(); ~Graph(); void Print() const; /* Print the graph to stdout. */ string Verbose; /* G = print graph at each step. P = print augmenting paths at each step. B = Basic: print graph at beginning and end. */ Node *Get_Node(const string &s); /* Create a node, or return it if already created. */ Edge *Get_Edge(Node *n1, Node *n2); /* Create an edge or return it if already created. */ int MaxFlow(); /* Do the max flow calculation for the graph. */ int Find_Augmenting_Path(); /* Find and process an augmenting path. */ bool DFS(Node *n); /* DFS to find an augmenting path - returns success. */ vector Path; /* The augmenting path. */ int NPaths; /* Number of paths for the calculation. */ int MaxCap; /* Maximum edge capacity */ Node *Source; /* Source and sink node. */ Node *Sink; vector Nodes; /* All of the nodes. */ vector Edges; /* All of the edges. */ map N_Map; /* The nodes, keyed by name. */ map E_Map; /* The edges, keyed by name. */ }; Edge *Graph::Get_Edge(Node *n1, Node *n2) { string en; Edge *e; en = n1->name + "->"; en += n2->name; if (E_Map.find(en) != E_Map.end()) return E_Map[en]; e = new Edge; e->name = en; E_Map[en] = e; Edges.push_back(e); e->original = 0; e->residual = 0; e->n1 = n1; e->n2 = n2; e->reverse = NULL; return e; } Node *Graph::Get_Node(const string &s) { Node *n; if (N_Map.find(s) != N_Map.end()) return N_Map[s]; n = new Node; n->name = s; n->visited = 0; N_Map[s] = n; Nodes.push_back(n); return n; } void Edge::Print() const { printf("[%s:%d]", name.c_str(), residual); } void Graph::Print() const { size_t i, j; Node *n; printf("Graph:\n"); for (i = 0; i < Nodes.size(); i++) { n = Nodes[i]; printf(" "); printf("Node: %s - ", n->name.c_str()); for (j = 0; j < n->adj.size(); j++) n->adj[j]->Print(); printf("\n"); } } Graph::Graph() { string s, nn, nn2, en; int cap; Node *n1, *n2; Edge *e, *r; MaxCap = 0; Source = NULL; Sink = NULL; while (cin >> s) { if (s == "SOURCE" || s == "SINK") { /* Set the source or sink (error checking for duplicates. */ if (!(cin >> nn)) exit(0); n1 = Get_Node(nn); if (s == "SOURCE") { if (Source != NULL) { cerr << "Two sources.\n"; exit(1); } Source = n1; } else { if (Sink != NULL) { cerr << "Two sinks.\n"; exit(1); } Sink = n1; } /* When you read an edge, create it, potentially creating */ } else if (s == "EDGE") { /* the nodes, set the capacities and reverse edges. */ if (!(cin >> nn >> nn2 >> cap)) exit(0); if (cap <= 0) exit(0); n1 = Get_Node(nn); n2 = Get_Node(nn2); e = Get_Edge(n1, n2); e->original += cap; e->residual += cap; if (e->residual > MaxCap) MaxCap = cap + 1; if (e->reverse == NULL) { /* This means that the edge was just created */ r = Get_Edge(n2, n1); e->reverse = r; r->reverse = e; n1->adj.push_back(e); n2->adj.push_back(r); } } } MaxCap *= 2; /* This is because you can add flow in both directions (just trust me) */ if (Source == NULL) { cerr << "No Source.\n"; exit(1); } if (Sink == NULL) { cerr << "No Sink.\n"; exit(1); } } Graph::~Graph() { size_t i; for (i = 0; i < Nodes.size(); i++) delete Nodes[i]; for (i = 0; i < Edges.size(); i++) delete Edges[i]; } int main(int argc, char **argv) { Graph *G; if (argc > 2) { cerr << "usage: netflow verbosity(BGP) - graph on stdin\n"; exit(1); } G = new Graph(); if (argc == 2) G->Verbose = argv[1]; if (G->Verbose.find('B') != string::npos) G->Print(); delete G; /* Doing this just to make sure that the destructor works */ }