Pagini recente » Cod sursa (job #2413081) | Cod sursa (job #2439041) | Cod sursa (job #1438388) | Cod sursa (job #330206) | Cod sursa (job #1759266)
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
// Class that represents a directed graph where you
// can find the min cost max flow with Bellman-Ford.
// Memory complexity: O(number_of_vertices ^ 2).
template<class F, class C>
class MinCostMaxFlowGraph {
public:
MinCostMaxFlowGraph(int num_vertices) : num_vertices_(num_vertices + 1) {
previous_vertex_.resize(num_vertices_);
distance_.resize(num_vertices_);
}
void AddEdge(int from, int to, F capacity, C cost, int index) {
neighbours_[from].push_back(to);
capacity_[from][to] += capacity;
cost_[from][to] += cost;
neighbours_[to].push_back(from);
cost_[to][from] -= cost;
index_[from][to] = index;
}
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) {
int previous_vertex = previous_vertex_[current_vertex];
flow_added = min(flow_added, capacity_[previous_vertex][current_vertex]
- flow_[previous_vertex][current_vertex]);
current_vertex = previous_vertex_[current_vertex];
}
current_vertex = sink;
while (current_vertex != source) {
int previous_vertex = previous_vertex_[current_vertex];
flow_[previous_vertex][current_vertex] += flow_added;
flow_[current_vertex][previous_vertex] -= flow_added;
current_vertex = previous_vertex_[current_vertex];
}
max_flow += flow_added;
min_cost += distance_[sink] * flow_added;
}
return make_pair(max_flow, min_cost);
}
F GetFlow(int from, int to) {
return flow_[from][to];
}
int GetIndex(int from, int to) {
return index_[from][to];
}
private:
bool PushFlow(int source, int sink) {
fill(previous_vertex_.begin(), previous_vertex_.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 : neighbours_[vertex]) {
F edge_capacity = capacity_[vertex][neighbour];
F edge_flow = flow_[vertex][neighbour];
C edge_cost = cost_[vertex][neighbour];
if (distance_[vertex] + edge_cost < distance_[neighbour]
&& edge_flow < edge_capacity) {
distance_[neighbour] = distance_[vertex] + edge_cost;
previous_vertex_[neighbour] = vertex;
if (!in_queue[neighbour]) {
in_queue[neighbour] = true;
q.push(neighbour);
}
}
}
}
return distance_[sink] != numeric_limits<C>::max();
}
static const int kMax = 605;
int num_vertices_;
vector<int> neighbours_[kMax];
F capacity_[kMax][kMax];
F flow_[kMax][kMax];
C cost_[kMax][kMax];
int index_[kMax][kMax];
vector<int> previous_vertex_;
vector<C> distance_;
};
int main() {
clock_t start = clock();
cin.sync_with_stdio(false);
ifstream cin("cmcm.in");
ofstream cout("cmcm.out");
int n, m, e;
cin >> n >> m >> e;
MinCostMaxFlowGraph<int, int> graph(n + m + 1);
for (int i = 1; i <= e; i++) {
int from, to, cost;
cin >> from >> to >> cost;
to += n;
graph.AddEdge(from, to, 1, cost, i);
}
int source = 0;
int sink = n + m + 1;
for (int i = 1; i <= n; i++) {
graph.AddEdge(source, i, 1, 0, 0);
}
for (int i = n + 1; i <= n + m; i++) {
graph.AddEdge(i, sink, 1, 0, 0);
}
pair<int, int> min_cost_max_flow = graph.GetMinCostMaxFlow(source, sink);
cout << min_cost_max_flow.first << " " << min_cost_max_flow.second << '\n';
for (int i = 1; i <= n; i++) {
for (int j = n + 1; j <= n + m; j++) {
if (graph.GetFlow(i, j)) {
cout << graph.GetIndex(i, j) << " ";
}
}
}
clock_t finish = clock();
cerr << fixed << 1.0 * (finish - start) / CLOCKS_PER_SEC << endl;
return 0;
}