Pagini recente » Cod sursa (job #2819278) | Cod sursa (job #213678) | Cod sursa (job #1372020) | Cod sursa (job #1976058) | Cod sursa (job #1758860)
#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).
class MinCostMaxFlowGraph {
public:
MinCostMaxFlowGraph(int num_vertices) : num_vertices_(num_vertices + 1) {}
void AddEdge(int from, int to, int capacity, int 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<int, int> GetMinCostMaxFlow(int source, int sink) {
int max_flow = 0;
int min_cost = 0;
while (PushFlow(source, sink)) {
int flow_added = kInf;
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);
}
int 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) {
bool in_queue[kMax];
for (int i = 0; i <= num_vertices_; i++) {
previous_vertex_[i] = -1;
distance_[i] = kInf;
in_queue[i] = 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]) {
int edge_capacity = capacity_[vertex][neighbour];
int edge_flow = flow_[vertex][neighbour];
int 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] != kInf;
}
const static int kMax = 605;
const static int kInf = 1 << 30;
int num_vertices_;
vector<int> neighbours_[kMax];
int capacity_[kMax][kMax];
int flow_[kMax][kMax];
int cost_[kMax][kMax];
int index_[kMax][kMax];
int previous_vertex_[kMax];
int distance_[kMax];
};
int main() {
cin.sync_with_stdio(false);
freopen("cmcm.in", "r", stdin);
freopen("cmcm.out", "w", stdout);
int n, m, e;
scanf("%d%d%d", &n, &m, &e);
MinCostMaxFlowGraph graph(n + m + 1);
for (int i = 1; i <= e; i++) {
int from, to, cost;
scanf("%d%d%d", &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);
printf("%d %d\n", min_cost_max_flow.first, min_cost_max_flow.second);
for (int i = 1; i <= n; i++) {
for (int j = n + 1; j <= n + m; j++) {
if (graph.GetFlow(i, j)) {
printf("%d ", graph.GetIndex(i, j));
}
}
}
return 0;
}