#include #include #include #include #include #include using namespace std; typedef multimap Adjlist; class Node { public: string name; Adjlist edges; Node *backedge; // For determining a path in augmenting paths. int visited; }; class Edge { public: Node *n1; // From node Node *n2; // To node Edge *reverse; // This lets you find your reverse edge quickly double capacity; Adjlist::iterator adj_ptr; // This lets you delete yourself // from the adjacently list quickly void Print(); }; class Graph { public: // Methods: Graph(); void Print(); Node *Get_Node_By_Name(string name); double GetFlow(); double FindAugmentingPath(); double DFS(Node *n); // Data: list path; map node_names; // All nodes by name. Node *source; Node *sink; }; void Edge::Print() { cout << "[" << n1->name << "->" << n2->name << ":" << capacity << "]"; } double Graph::DFS(Node *n) { Adjlist::reverse_iterator alit; Edge *e; double flow; n->visited = 1; for (alit = n->edges.rbegin(); alit != n->edges.rend(); alit++) { e = alit->second; if (e->capacity > 0) { if (e->n2 == sink) { path.push_front(e); return e->capacity; } else if (!e->n2->visited) { flow = DFS(e->n2); if (flow > 0) { path.push_front(e); return (flow < e->capacity) ? flow : e->capacity; } } } } return 0; } double Graph::FindAugmentingPath() { map ::iterator nptr; list ::iterator pit; Adjlist::iterator alit; Node *n; double flow; Edge *e; for (nptr = node_names.begin(); nptr != node_names.end(); nptr++) { n = nptr->second; n->visited = 0; } flow = DFS(source); if (flow > 0) { while (!path.empty()) { pit = path.begin(); e = *pit; path.erase(pit); // cout << "Path edge "; // e->Print(); // cout << endl; e->n1->edges.erase(e->adj_ptr); e->capacity -= flow; e->adj_ptr = e->n1->edges.insert(make_pair(e->capacity, e)); if (e->reverse == NULL) { e->reverse = new Edge; e->reverse->reverse = e; e->reverse->capacity = flow; e->reverse->n1 = e->n2; e->reverse->n2 = e->n1; } else { e->n2->edges.erase(e->reverse->adj_ptr); e->reverse->capacity += flow; } e->reverse->adj_ptr = e->n2->edges.insert(make_pair(e->reverse->capacity, e->reverse)); } } return flow; } double Graph::GetFlow() { double maxflow; double flow; maxflow = 0; while (1) { flow = FindAugmentingPath(); if (flow == 0) return maxflow; maxflow += flow; } } Node *Graph::Get_Node_By_Name(string name) // Creates the node if it does not yet exist { Node *n; map ::iterator nptr; nptr = node_names.find(name); if (nptr == node_names.end()) { n = new Node; n->name = name; n->backedge = NULL; n->visited = 0; node_names.insert(make_pair(name, n)); return n; } else { return nptr->second; } } Graph::Graph() // Create a graph from standard input. { string s, name1, name2; Node *n1; Node *n2; Edge *e; double cap; map ::iterator eptr; map edge_names; source = NULL; sink = NULL; while (!cin.fail()) { cin >> s; if (!cin.fail()) { if (s == "SOURCE") { if (source != NULL) { cerr << "Bad Graph -- multiple sources\n"; exit(1); } cin >> s; if (cin.fail()) { cerr << "Bad Graph - no source node given\n"; exit(1); } source = Get_Node_By_Name(s); } else if (s == "SINK") { if (sink != NULL) { cerr << "Bad Graph -- multiple sources\n"; exit(1); } cin >> s; if (cin.fail()) { cerr << "Bad Graph - no source node given\n"; exit(1); } sink = Get_Node_By_Name(s); } else if (s == "EDGE") { cin >> name1 >> name2 >> cap; if (cin.fail()) { cerr << "Bad Graph -- bad edge specification\n"; exit(1); } if (cap <= 0) { cerr << "Bad Graph -- bad edge capacity\n"; exit(1); } n1 = Get_Node_By_Name(name1); n2 = Get_Node_By_Name(name2); s = name1 + " -> " + name2; if (edge_names.find(s) != edge_names.end()) { cerr << "Bad Graph -- duplicate edge " << s << endl; exit(1); } e = new Edge; edge_names.insert(make_pair(s, e)); e->capacity = cap; e->n1 = n1; e->n2 = n2; e->adj_ptr = n1->edges.insert(make_pair(cap, e)); s = name2 + " -> " + name1; eptr = edge_names.find(s); if (eptr == edge_names.end()) { e->reverse = NULL; } else { e->reverse = eptr->second; e->reverse->reverse = e; } } } } if (source == NULL || sink == NULL) { cerr << "Bad Graph -- no source or no sink\n"; exit(1); } } void Graph::Print() { Adjlist::iterator alit; map ::iterator nit; list edges; list ::iterator elit; Edge *e; Node *n; cout << "Source: " << source->name << ", Sink: " << sink->name << endl; for (nit = node_names.begin(); nit != node_names.end(); nit++) { n = nit->second; cout << "Node " << n->name << ", Edges:"; for (alit = n->edges.begin(); alit != n->edges.end(); alit++) { e = alit->second; e->Print(); edges.push_back(e); } cout << endl; } for (elit = edges.begin(); elit != edges.end(); elit++) { e = *elit; e->Print(); if (e->reverse == NULL) { cout << " No reverse edge.\n"; } else { cout << " Reverse edge: "; e->reverse->Print(); cout << endl; } } } main() { Graph *g; double flow; g = new Graph(); flow = g->GetFlow(); cout << "Flow is " << flow << endl; }