#include #include #include #include #include #include using namespace std; class Node { public: string name; vector adj; int visited; }; class Edge { public: string name; Node *n1; Node *n2; Edge *reverse; double original; double residual; double flow; }; class Graph { public: Graph(); ~Graph(); void Print(); Node *Get_Node(string &s); Edge *Get_Edge(Node *n1, Node *n2); double Find_Max_Flow(); double Find_Augmenting_Path(); int DFS(Node *n); vector Path; vector Cut; Node *Source; Node *Sink; vector Nodes; vector Edges; map N_Map; map E_Map; }; double Graph::Find_Max_Flow() { double total; double f; Edge *e; Node *n; int i, j; for (i = 0; i < Edges.size(); i++) { e = Edges[i]; e->flow = 0; e->residual = e->original; } total = 0; while (1) { f = Find_Augmenting_Path(); if (f == 0) { Cut.clear(); for (i = 0; i < Nodes.size(); i++) { n = Nodes[i]; if (n->visited) { for (j = 0; j < n->adj.size(); j++) { e = n->adj[j]; if (e->original > 0 && !e->n2->visited) Cut.push_back(e); } } } return total; } else { total += f; } } } double Graph::Find_Augmenting_Path() { int i; double f; Edge *e; for (i = 0; i < Nodes.size(); i++) Nodes[i]->visited = 0; Path.clear(); if (DFS(Source)) { f = Path[0]->residual; for (i = 1; i < Path.size(); i++) { if (Path[i]->residual < f) f = Path[i]->residual; } for (i = 0; i < Path.size(); i++) { e = Path[i]; e->residual -= f; e->flow += f; e->reverse->residual += f; } printf("Found path with flow of %.3lf:", f); for (i = Path.size()-1; i >= 0; i--) printf(" %s", Path[i]->name.c_str()); printf("\n"); return f; } else { return 0; } } int Graph::DFS(Node *n) { int i; Edge *e; double f; if (n->visited) return 0; n->visited = 1; if (n == Sink) return 1; for (i = 0; i < n->adj.size(); i++) { e = n->adj[i]; if (e->residual > 0) { if (DFS(e->n2)) { Path.push_back(e); return 1; } } } return 0; } void Graph::Print() { Node *n; Edge *e; int i, j; printf("Source: %s\n", Source->name.c_str()); printf("Sink: %s\n", Sink->name.c_str()); for (i = 0; i < Nodes.size(); i++) { n = Nodes[i]; printf("Node %s:", n->name.c_str()); for (j = 0; j < n->adj.size(); j++) { e = n->adj[j]; printf(" (%s:%.3lf)", e->name.c_str(), e->original); } printf("\n"); } } Graph::Graph() { string s, f, t; double cap; Node *n1, *n2; Edge *e; Source = NULL; Sink = NULL; while (cin >> s) { if (s == "SOURCE") { cin >> s; if (Source != NULL) { fprintf(stderr, "Can't specify two sources\n"); exit(1); } Source = Get_Node(s); } else if (s == "SINK") { cin >> s; if (Sink != NULL) { fprintf(stderr, "Can't specify two sinks\n"); exit(1); } Sink = Get_Node(s); } else if (s == "EDGE") { cin >> f >> t >> cap; n1 = Get_Node(f); n2 = Get_Node(t); e = Get_Edge(n1, n2); e->original += cap; if (e->reverse == NULL) { e->reverse = Get_Edge(n2, n1); e->reverse->reverse = e; n1->adj.push_back(e); n2->adj.push_back(e->reverse); } } } if (Source == NULL) { fprintf(stderr, "No Source.\n"); exit(1); } if (Sink == NULL) { fprintf(stderr, "No Sink.\n"); exit(1); } } Graph::~Graph() { int i; for (i = 0; i < Nodes.size(); i++) delete(Nodes[i]); for (i = 0; i < Edges.size(); i++) delete(Edges[i]); } Node *Graph::Get_Node(string &s) { map ::iterator nit; Node *n; nit = N_Map.find(s); if (nit != N_Map.end()) return nit->second; n = new Node; n->name = s; Nodes.push_back(n); N_Map.insert(make_pair(s, n)); return n; } Edge *Graph::Get_Edge(Node *n1, Node *n2) { map ::iterator eit; Edge *e; string name; name = n1->name + "->"; name += n2->name; eit = E_Map.find(name); if (eit != E_Map.end()) return eit->second; e = new Edge; e->name = name; e->n1 = n1; e->n2 = n2; e->original = 0; e->residual = 0; e->flow = 0; e->reverse = NULL; Edges.push_back(e); E_Map.insert(make_pair(name, e)); return e; } main() { Graph *g; double f; int i; g = new Graph(); f = g->Find_Max_Flow(); printf("Max flow is %.3lf\n", f); printf("Cut:"); for (i = 0; i < g->Cut.size(); i++) printf(" %s", g->Cut[i]->name.c_str()); printf("\n"); }