Pagini recente » Cod sursa (job #581577) | Cod sursa (job #590562) | Cod sursa (job #2762635) | Cod sursa (job #748338) | Cod sursa (job #3191080)
#include <bits/stdc++.h>
using namespace std;
ifstream in("cc.in");
ofstream out("cc.out");
int N, nodDestinatie, dist;
vector<vector<int>> listaAdj, capacitate, flow, matriceDist;
vector<int> nodAnterior, minDist;
int rezultat;
// Funcție pentru parcurgerea în lățime (BFS) pentru găsirea unui drum de la sursă la destinație
int bfs() {
// Inițializarea nodurilor precedente și a distanței minime pentru fiecare iterație a BFS
nodAnterior.assign(nodDestinatie + 1, -1);
minDist.assign(nodDestinatie + 1, INT_MAX);
minDist[0] = 0;
queue<pair<int, int>> q;
q.push({0, INT_MAX});
while (!q.empty()) {
int curent = q.front().first, minFlow = q.front().second;
q.pop();
// Parcurgerea vecinilor nodului curent în graf
for (auto &urmator : listaAdj[curent]) {
// Verificarea dacă există o capacitate nefolosită pe muchia de la nodul curent la nodul vecin
if (minDist[urmator] > minDist[curent] + matriceDist[curent][urmator] && capacitate[curent][urmator] > flow[curent][urmator]) {
// Actualizarea nodului vecin și adăugarea la coadă pentru explorare ulterioară
nodAnterior[urmator] = curent;
int residualCap = capacitate[curent][urmator] - flow[curent][urmator];
int urmatorMinFlow = residualCap > minFlow ? minFlow : residualCap;
minDist[urmator] = minDist[curent] + matriceDist[curent][urmator];
q.push({urmator, urmatorMinFlow});
}
}
}
// Returnează true dacă a fost găsit un drum de la sursă la destinație
return nodAnterior[nodDestinatie] >= 0;
}
// Algoritmul Edmonds-Karp pentru găsirea fluxului maxim și a distanței minime
void edmondsKarpAlgorithm() {
while (true) {
int flowOfPath = bfs();
// Dacă nu mai există drumuri augmentate, se oprește
if (!flowOfPath) break;
int curent = nodDestinatie;
// Refacerea drumului și actualizarea fluxului pe tot traseul
while (curent != 0) {
int anterior = nodAnterior[curent];
flow[anterior][curent] += flowOfPath;
flow[curent][anterior] -= flowOfPath;
curent = anterior;
}
// Adăugarea la distanța totală
rezultat += minDist[nodDestinatie];
}
}
int main() {
in >> N;
nodDestinatie = 2 * N + 1;
// Inițializarea vectorilor și matricelor pentru graful de flux
nodAnterior.resize(nodDestinatie + 1);
minDist.resize(nodDestinatie + 1);
listaAdj.resize(nodDestinatie + 1, {});
capacitate.assign(nodDestinatie + 1, vector<int>(nodDestinatie + 1, 0));
flow.resize(nodDestinatie + 1, vector<int>(nodDestinatie + 1, 0));
matriceDist.resize(nodDestinatie + 1, vector<int>(nodDestinatie + 1, 0));
// Construirea grafului și a matricelor de capacitate și distanță
for (int i = 1; i <= N; i++) {
// Adăugarea muchiilor de la sursă către nodurile concurenților
listaAdj[0].push_back(i);
listaAdj[i].push_back(0);
capacitate[0][i] = 1;
for (int j = 1; j <= N; j++) {
in >> dist;
// Adăugarea muchiilor între concurenți și calculatoare și inițializarea matricii de distanțe
listaAdj[i].push_back(j + N);
listaAdj[j + N].push_back(i);
capacitate[i][j + N] = 1;
matriceDist[i][j + N] = dist;
matriceDist[j + N][i] = -dist;
}
}
// Adăugarea muchiilor de la calculatoare la nodul destinație
for (int i = 1; i <= N; i++) {
listaAdj[i + N].push_back(nodDestinatie);
listaAdj[nodDestinatie].push_back(i + N);
capacitate[i + N][nodDestinatie] = 1;
}
// Apelarea algoritmului Edmonds-Karp
edmondsKarpAlgorithm();
// Scrierea rezultatului în fișierul de ieșire
out << rezultat;
return 0;
}