Pagini recente » Cod sursa (job #2519351) | Cod sursa (job #2082312) | Cod sursa (job #2325498) | Cod sursa (job #362152) | Cod sursa (job #2240412)
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <queue>
#include <tuple>
using namespace std;
class Graph {
public:
Graph(int size):
m_capacity(size, vector<int>(size, 0)),
m_edges(size),
m_size(size) {}
void add_edge(int from, int to, int capacity) {
m_capacity[from][to] += capacity;
m_edges[from].push_back(to);
m_edges[to].push_back(from);
}
void remove_duplicates() {
for (auto &edges: m_edges) {
sort(edges.begin(), edges.end());
edges.erase(unique(edges.begin(), edges.end()), edges.end());
}
}
int max_flow(int source, int destination) {
int answer = 0;
while (true) {
auto edges = get_level_graph_edges(source, destination);
if (edges.empty())
return answer;
int flow;
do {
flow = tidal_phase(edges, source, destination);
answer += flow;
} while (flow > 0);
}
return answer;
}
private:
vector< pair<int, int> > get_level_graph_edges(int source, int destination) {
// Find accessible nodes from destination, not really needed but speeds up a bit
queue<int> Q;
Q.push(destination);
vector<int> level(m_size, -2);
level[destination] = 0;
while (!Q.empty()) {
int x = Q.front();
Q.pop();
if (x == source)
break;
for (auto &y : m_edges[x])
if (m_capacity[y][x] > 0 && level[y] == -2) {
level[y] = level[x] + 1;
Q.push(y);
}
}
// level graph edges
vector< pair<int, int> > edges;
if (level[source] == -2) {
return edges;
}
while (!Q.empty())
Q.pop();
Q.push(source);
vector<bool> used(m_size, false);
used[source] = true;
while (!Q.empty()) {
int x = Q.front();
Q.pop();
for (auto &y : m_edges[x])
if (m_capacity[x][y] > 0 && level[y] == level[x] - 1) {
edges.emplace_back(x, y);
if (used[y] == false) {
used[y] = true;
Q.push(y);
}
}
}
return edges;
}
int tidal_phase(const vector< pair<int, int> > &edges, int source, int destination) {
vector<int> high(m_size, 0);
high[source] = numeric_limits<int>::max();
vector<int> permitted(edges.size());
for (int i = 0; i < int(edges.size()); ++i) {
int from, to; tie(from, to) = edges[i];
permitted[i] = min(high[from], m_capacity[from][to]);
high[to] += permitted[i];
}
if (high[destination] == 0)
return 0;
vector<int> low(m_size, 0);
low[destination] = high[destination];
for (int i = edges.size() - 1; i >= 0; --i) {
int from, to; tie(from, to) = edges[i];
int limit = min(high[from] - low[from], low[to]);
permitted[i] = min(permitted[i], limit);
low[from] += permitted[i];
low[to] -= permitted[i];
}
fill(high.begin(), high.end(), 0);
high[source] = low[source];
for (int i = 0; i < int(edges.size()); ++i) {
int from, to; tie(from, to) = edges[i];
int flow = min(permitted[i], high[from]);
high[from] -= flow;
high[to] += flow;
m_capacity[from][to] -= flow;
m_capacity[to][from] += flow;
}
return high[destination];
}
vector< vector<int> > m_capacity;
vector< vector<int> > m_edges;
int m_size;
};
int main() {
ifstream cin("maxflow.in");
ofstream cout("maxflow.out");
int N, M; cin >> N >> M;
Graph G(N);
for (int i = 0; i < M; ++i) {
int x, y, capacity; cin >> x >> y >> capacity;
G.add_edge(x - 1, y - 1, capacity);
}
G.remove_duplicates();
cout << G.max_flow(0, N - 1) << "\n";
}