Pagini recente » Cod sursa (job #2593112) | Cod sursa (job #2707300) | Cod sursa (job #590148) | Cod sursa (job #1191226) | Cod sursa (job #3189917)
#include <fstream>
#include <vector>
#include <queue>
#define E 100001
#define N 202
using namespace std;
ifstream fin("cc.in");
ofstream fout("cc.out");
// Structura pentru a reprezenta o muchie în graf
struct Edge {
int to, cost, capacity, reverse_edge;
};
int n, totalCost = 0;
vector<Edge> graph[N]; // lista de adiacență a grafului
int dist[N], prevNode[N], prevEdge[N];
// Funcția pentru adăugarea unei muchii în graf
void addEdge(int u, int v, int cost) {
graph[u].push_back({v, cost, 1, static_cast<int>(graph[v].size())}); // adăugarea muchiei
graph[v].push_back({u, -cost, 0, static_cast<int>(graph[u].size()) - 1});
}
// Algoritmul Dijkstra pentru a găsi drumul cel mai scurt
bool dijkstra(int s, int t) {
fill(dist, dist + N, E); // inițializarea distanțelor cu o valoare mare
dist[s] = 0; // distanța de la sursă la sursă este 0
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
pq.push({0, s}); // adăugarea sursă în coadă
while (!pq.empty()) {
auto [d, u] = pq.top(); // extragerea nodului cu distanța minimă
pq.pop(); // ștergerea nodului din coadă
if (dist[u] < d) continue; // dacă distanța curentă este mai mare, trecem la următorul nod
for (int i = 0; i < graph[u].size(); ++i) {
Edge &e = graph[u][i];
int v = e.to;
// verificăm dacă putem să ne deplasăm la v printr-o muchie neutilizată
if (e.capacity > 0 && dist[v] > dist[u] + e.cost) {
dist[v] = dist[u] + e.cost; // actualizăm distanța
prevNode[v] = u; // nodul anterior
prevEdge[v] = i; // muchia anterioră
pq.push({dist[v], v}); // adăugăm nodul în coada de priorități
}
}
}
return dist[t] != E; // returnăm dacă există un drum până la destinație
}
// Algoritmul pentru calcularea fluxului maxim cu cost minim
int minCostMaxFlow(int s, int t) {
int flow = 0; // fluxul maxim
while (dijkstra(s, t)) {
int minFlow = E; // fluxul minim posibil
for (int v = t; v != s; v = prevNode[v]) {
Edge &e = graph[prevNode[v]][prevEdge[v]]; // muchia curentă
minFlow = min(minFlow, e.capacity); // calculăm fluxul minim
}
for (int v = t; v != s; v = prevNode[v]) {
Edge &e = graph[prevNode[v]][prevEdge[v]]; // muchia curentă
e.capacity -= minFlow; // reducem capacitatea
graph[v][e.reverse_edge].capacity += minFlow; // actualizăm capacitatea muchiei inverse
}
flow += minFlow; // actualizăm fluxul
totalCost += dist[t] * minFlow; // calculăm costul total
}
return flow; // returnăm fluxul maxim
}
// Funcția principală a programului
int main() {
fin >> n; // citim numărul de noduri
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
int k;
fin >> k;
addEdge(i, n + j + 1, k); // adăugăm muchia în graf
}
}
for (int i = 1; i <= n; ++i) {
addEdge(0, i, 0); // adăugăm muchia de la sursă la nodurile initiale cu cost 0
addEdge(i + n + 1, n + 1, 0); // adăugăm muchia de la nodurile finale la destinație cu cost 0
}
int maxFlow = minCostMaxFlow(0, n + 1); // calculăm fluxul maxim
fout << totalCost << "\n";
fin.close();
fout.close();
return 0;
}