Pagini recente » Cod sursa (job #1522787) | Cod sursa (job #208502) | Cod sursa (job #3240598) | Cod sursa (job #117022) | Cod sursa (job #1758326)
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
template<class F, class C>
class MinCostMaxFlowGraph {
public:
MinCostMaxFlowGraph(int num_vertices) : num_vertices_(num_vertices + 1) {
neighbours_.resize(num_vertices_);
previous_edge_.resize(num_vertices_);
distance_.resize(num_vertices_);
}
void AddEdge(int from, int to, F capacity, C cost) {
neighbours_[from].push_back(edges_.size());
edges_.emplace_back(from, to, capacity, cost);
neighbours_[to].push_back(edges_.size());
edges_.emplace_back(to, from, 0, -cost);
}
pair<F, C> GetMinCostMaxFlow(int source, int sink) {
F max_flow = 0;
C min_cost = 0;
while (PushFlow(source, sink)) {
F flow_added = numeric_limits<F>::max();
int current_vertex = sink;
while (current_vertex != source) {
F edge_flow = edges_[previous_edge_[current_vertex]].flow_;
C edge_capacity = edges_[previous_edge_[current_vertex]].capacity_;
flow_added = min(flow_added, edge_capacity - edge_flow);
current_vertex = edges_[previous_edge_[current_vertex]].from_;
}
current_vertex = sink;
while (current_vertex != source) {
edges_[previous_edge_[current_vertex]].flow_ += flow_added;
edges_[previous_edge_[current_vertex] ^ 1].flow_ -= flow_added;
current_vertex = edges_[previous_edge_[current_vertex]].from_;
}
max_flow += flow_added;
min_cost += distance_[sink] * flow_added;
}
return make_pair(max_flow, min_cost);
}
private:
struct Edge {
Edge(int from, int to, F capacity, C cost) :
from_(from), to_(to), flow_(0), capacity_(capacity), cost_(cost) {}
int from_;
int to_;
F flow_;
F capacity_;
C cost_;
};
bool PushFlow(int source, int sink) {
fill(previous_edge_.begin(), previous_edge_.end(), -1);
fill(distance_.begin(), distance_.end(), numeric_limits<C>::max());
vector<bool> in_queue(num_vertices_, false);
queue<int> q;
distance_[source] = 0;
in_queue[source] = true;
q.push(source);
while (!q.empty()) {
int vertex = q.front();
q.pop();
in_queue[vertex] = false;
if (vertex == sink) {
continue;
}
for (int neighbour_edge_index : neighbours_[vertex]) {
int neighbour = edges_[neighbour_edge_index].to_;
int edge_flow = edges_[neighbour_edge_index].flow_;
int edge_capacity = edges_[neighbour_edge_index].capacity_;
int edge_cost = edges_[neighbour_edge_index].cost_;
if (distance_[vertex] + edge_cost < distance_[neighbour]
&& edge_flow < edge_capacity) {
distance_[neighbour] = distance_[vertex] + edge_cost;
previous_edge_[neighbour] = neighbour_edge_index;
if (!in_queue[neighbour]) {
in_queue[neighbour] = true;
q.push(neighbour);
}
}
}
}
return distance_[sink] != numeric_limits<C>::max();
}
int num_vertices_;
vector<Edge> edges_;
vector<vector<int>> neighbours_;
vector<int> previous_edge_;
vector<C> distance_;
};
int main() {
cin.sync_with_stdio(false);
ifstream cin("fmcm.in");
ofstream cout("fmcm.out");
int n, m, source, sink;
cin >> n >> m >> source >> sink;
MinCostMaxFlowGraph<int, int> graph(n);
for (; m; m--) {
int from, to, capacity, cost;
cin >> from >> to >> capacity >> cost;
graph.AddEdge(from, to, capacity, cost);
}
cout << graph.GetMinCostMaxFlow(source, sink).second << '\n';
return 0;
}