Pagini recente » Cod sursa (job #631625) | Cod sursa (job #2288788) | Cod sursa (job #2804471) | Cod sursa (job #244045) | Cod sursa (job #1175142)
#include <fstream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
class Graph {
public:
static const int NIL = -1;
static const int oo = 0x3f3f3f3f;
class Edge {
public:
int from, to, capacity, flow;
Edge(const int _from = NIL, const int _to = NIL, const int _capacity = 0):
from(_from),
to(_to),
capacity(_capacity),
flow(0) {}
bool IsSaturated() const {
return flow == capacity;
}
};
Graph(const int _V = 0):
V(_V),
E(0),
G(vector< vector<int> >(_V, vector<int>())),
edges(vector<Edge>()) {}
int Size() const {
return V;
}
void AddEdge(const Edge &e) {
edges.push_back(e);
G[e.from].push_back(E++);
}
int MaximumFlow(const int source, const int sink) {
InitializeNetwork();
int maxFlow = 0;
vector<int> father;
while (BFS(source, sink, father)) {
for (vector<int>::const_iterator e = G[sink].begin(); e != G[sink].end(); ++e) {
if (edges[NonE(*e)].IsSaturated() || father[edges[*e].to] == NIL)
continue;
father[sink] = NonE(*e);
int flow = oo;
for (int x = sink; x != source; x = edges[father[x]].from)
flow = min(flow, edges[father[x]].capacity - edges[father[x]].flow);
for (int x = sink; x != source; x = edges[father[x]].from) {
edges[father[x]].flow += flow;
edges[NonE(father[x])].flow -= flow;
}
maxFlow += flow;
}
}
ClearResidualNetwork();
return maxFlow;
}
private:
int V, E;
vector< vector<int> > G;
vector<Edge> edges;
int NonE(const int e) const {
if (e < E)
return e + E;
else
return e - E;
}
void InitializeNetwork() {
for (int e = 0; e < E; ++e) {
edges[e].flow = 0;
edges.push_back(Edge(edges[e].to, edges[e].from, 0));
G[edges[e].to].push_back(NonE(e));
}
}
bool BFS(const int source, const int destination, vector<int> &father) const {
father = vector<int>(V, NIL);
father[source] = 2 * E;
queue<int> q;
for (q.push(source); !q.empty(); q.pop()) {
int x = q.front();
if (x == destination)
continue;
for (vector<int>::const_iterator e = G[x].begin(); e != G[x].end(); ++e) {
if (!edges[*e].IsSaturated() && father[edges[*e].to] == NIL) {
father[edges[*e].to] = *e;
q.push(edges[*e].to);
}
}
}
return father[destination] != NIL;
}
void ClearResidualNetwork() {
for (; int(edges.size()) > E; edges.pop_back())
G[edges.back().from].pop_back();
}
};
Graph G;
int MaxFlow;
void Solve() {
MaxFlow = G.MaximumFlow(0, G.Size() - 1);
}
void Read() {
ifstream in("maxflow.in");
int V, E;
in >> V >> E;
G = Graph(V);
for (; E > 0; --E) {
int from, to, capacity;
in >> from >> to >> capacity;
G.AddEdge(Graph::Edge(from - 1, to - 1, capacity));
}
in.close();
}
void Print() {
ofstream out("maxflow.out");
out << MaxFlow << "\n";
out.close();
}
int main() {
Read();
Solve();
Print();
return 0;
}