Pagini recente » Cod sursa (job #1762073) | Cod sursa (job #712814) | Cod sursa (job #1031855) | Cod sursa (job #474773) | Cod sursa (job #1255876)
#include <algorithm>
#include <fstream>
#include <limits>
#include <queue>
#include <utility>
#include <vector>
using namespace std;
const int INF = numeric_limits<int>::max();
const int MAXN = 301;
const int MAXNN = 601;
int capacity[MAXNN][MAXNN], weight[MAXNN][MAXNN], edge_index[MAXN][MAXN];
int bellman_ford(
const int source,
const int sink,
vector<int>& tree,
const vector<vector<int>>& rG) {
vector<int> D(rG.size(), INF);
fill(tree.begin(), tree.end(), -1);
queue<int> Q;
vector<bool> inQ(rG.size(), false);
Q.push(source);
inQ[source] = true;
tree[source] = source;
D[source] = 0;
while (!Q.empty()) {
int u = Q.front(); Q.pop();
inQ[u] = false;
for (int v : rG[u])
if (capacity[u][v] && D[v] > D[u] + weight[u][v]) {
D[v] = D[u] + weight[u][v];
tree[v] = u;
if (!inQ[v]) {
Q.push(v);
inQ[v] = true;
}
}
}
return D[sink];
}
inline void augmentFlow(
vector<int>& matching,
const int flow,
int v,
const vector<int>& tree) {
int nu = matching.size() - 1;
for (int u = tree[v]; u != v; v = u, u = tree[v]) {
capacity[u][v] -= flow;
capacity[v][u] += flow;
if ((0 < u && u <= nu) && (nu < v && v < tree.size() - 1)) {
matching[u] = v - nu;
}
}
}
pair<int, int> minCostMaxFlow(
const int source,
const int sink,
vector<int>& matching,
const vector<vector<int>>& rG) {
int flow = 0, cost = 0;
vector<int> tree(rG.size());
while (true) {
int path_cost = bellman_ford(source, sink, tree, rG);
if (tree[sink] == -1) break;
augmentFlow(matching, 1, sink, tree);
flow++;
cost += path_cost;
}
return make_pair(flow, cost);
}
int main() {
ifstream fin("cmcm.in");
ofstream fout("cmcm.out");
int NU, NV, edges; fin >> NU >> NV >> edges;
int source = 0, sink = NU + NV + 1, N = NU + NV + 2;
// residual graph and residual capacity
vector<vector<int>> rG(N);
// necessary because of stupid, stupid output format for this problem :(
vector<int> matching(NU+1, 0);
//vector<vector<int>> edge_index(NU+1, vector<int>(NV+1, 0));
for (int u, v, z, i = 1; edges; --edges, ++i) {
fin >> u >> v >> z;
edge_index[u][v] = i;
v += NU;
rG[u].push_back(v); capacity[u][v] = 1;
rG[v].push_back(u);
weight[u][v] = z;
weight[v][u] = -z;
// add edges in the residual graph to the source and the sink
rG[source].push_back(u); capacity[source][u] = 1;
rG[u].push_back(source);
rG[v].push_back(sink); capacity[v][sink] = 1;
rG[sink].push_back(v);
}
pair<int, int> result = minCostMaxFlow(source, sink, matching, rG);
fout << result.first << ' ' << result.second << '\n';
for (int u = 1; u <= NU; ++u) if (matching[u])
fout << edge_index[u][matching[u]] << ' ';
fout << endl;
return 0;
}