Pagini recente » Cod sursa (job #1096302) | Cod sursa (job #1048860) | Cod sursa (job #1490644) | Cod sursa (job #2836992) | Cod sursa (job #3187625)
#include <fstream>
#include <climits>
#include <vector>
#include <queue>
using namespace std;
ifstream fin("cc.in");
ofstream fout("cc.out");
struct Edge {
int to, flow, capacity, cost, residual;
};
vector<vector<Edge>> network;
void add_edge(int u, int v, int capacity, int cost) {
network[u].push_back({v, 0, capacity, cost, (int) network[v].size()});
network[v].push_back({u, 0, 0, -cost, (int) network[u].size() - 1});
}
int min_cost_flow(int source, int sink) {
int answer = 0;
while (true) {
vector<int> distance (network.size(), INT_MAX);
vector<pair<int, int>> from (network.size());
priority_queue<pair<int,int>, vector<pair<int, int>>, greater<>> pq;
pq.push({0, source});
distance[source] = 0;
while (!pq.empty()) {
int dist = pq.top().first;
int u = pq.top().second;
pq.pop();
if (dist != distance[u])
continue;
for (int i = 0;i < network[u].size(); ++i) {
int capacity = network[u][i].capacity;
int residual = network[u][i].residual;
int flow = network[u][i].flow;
int cost = network[u][i].cost;
int v = network[u][i].to;
if (capacity - flow > 0 && distance[u] < INT_MAX && distance[u] + cost < distance[v]) {
distance[v] = distance[u] + cost;
pq.push({distance[v], v});
from[v] = {u, i};
}
}
}
if (distance[sink] == INT_MAX)
break;
int bottleneck = INT_MAX;
for (int node = sink; node != source; node = from[node].first) {
int u = from[node].first;
int v = from[node].second;
bottleneck = min(bottleneck, network[u][v].capacity - network[u][v].flow);
}
if (bottleneck != 1)
break;
for (int node = sink; node != source; node = from[node].first) {
int u = from[node].first;
int v = from[node].second;
network[u][v].flow += bottleneck;
network[v][network[u][v].residual].flow -= bottleneck;
answer += bottleneck * network[u][v].cost;
}
}
return answer;
}
int main() {
int n;
fin >> n;
network.resize(2 * n + 2);
int source = 2 * n, sink = 2 * n + 1;
for (int i = 0;i < n; ++i) {
add_edge(source, i, 1, 0);
add_edge(i + n, sink, 1, 0);
}
for (int i = 0;i < n;++i) {
for (int j = 0;j < n;++j) {
int cost;
fin >> cost;
add_edge(i, j + n, 1, cost);
}
}
fout << min_cost_flow(source, sink);
fin.close();
fout.close();
return 0;
}