Pagini recente » Cod sursa (job #3039664) | Cod sursa (job #3126971) | Cod sursa (job #1639205) | Cod sursa (job #28702) | Cod sursa (job #3190429)
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;
ifstream inputFile("cc.in");
ofstream outputFile("cc.out");
int numNodes, sourceNode, targetNode, dist;
vector<vector<int>> adjacencyList, capacity, flow, distanceMatrix;
vector<int> previousNode, minDistance;
int result;
// 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
previousNode.assign(targetNode + 1, -1);
minDistance.assign(targetNode + 1, INT_MAX);
minDistance[0] = 0;
queue<pair<int, int>> q;
q.push({0, INT_MAX});
while (!q.empty()) {
int current = q.front().first, minFlowUntilNow = q.front().second;
q.pop();
// Parcurgerea vecinilor nodului curent în graf
for (auto &next : adjacencyList[current]) {
// Verificarea dacă există o capacitate nefolosită pe muchia de la nodul curent la nodul vecin
if (minDistance[next] > minDistance[current] + distanceMatrix[current][next] && capacity[current][next] > flow[current][next]) {
// Actualizarea nodului vecin și adăugarea la coadă pentru explorare ulterioară
previousNode[next] = current;
int residualCapacity = capacity[current][next] - flow[current][next];
int nextMinFlow = residualCapacity > minFlowUntilNow ? minFlowUntilNow : residualCapacity;
minDistance[next] = minDistance[current] + distanceMatrix[current][next];
q.push({next, nextMinFlow});
}
}
}
// Returnează true dacă a fost găsit un drum de la sursă la destinație
return previousNode[targetNode] >= 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 current = targetNode;
// Refacerea drumului și actualizarea fluxului pe tot traseul
while (current != 0) {
int previous = previousNode[current];
flow[previous][current] += flowOfPath;
flow[current][previous] -= flowOfPath;
current = previous;
}
// Adăugarea la distanța totală
result += minDistance[targetNode];
}
}
int main() {
// Citirea numărului de noduri din fișierul de intrare
inputFile >> numNodes;
// Calcularea nodului destinație în graf
targetNode = 2 * numNodes + 1;
// Inițializarea vectorilor și matricelor pentru graful de flux
previousNode.resize(targetNode + 1);
minDistance.resize(targetNode + 1);
adjacencyList.resize(targetNode + 1, {});
capacity.assign(targetNode + 1, vector<int>(targetNode + 1, 0));
flow.resize(targetNode + 1, vector<int>(targetNode + 1, 0));
distanceMatrix.resize(targetNode + 1, vector<int>(targetNode + 1, 0));
// Construirea grafului și a matricelor de capacitate și distanță
for (int i = 1; i <= numNodes; i++) {
// Adăugarea muchiilor de la sursă către nodurile concurenților
adjacencyList[0].push_back(i);
adjacencyList[i].push_back(0);
capacity[0][i] = 1;
for (int j = 1; j <= numNodes; j++) {
// Citirea distanței dintre concurentul i și calculatorul j
inputFile >> dist;
// Adăugarea muchiilor între concurenți și calculatoare și inițializarea matricii de distanțe
adjacencyList[i].push_back(j + numNodes);
adjacencyList[j + numNodes].push_back(i);
capacity[i][j + numNodes] = 1;
distanceMatrix[i][j + numNodes] = dist;
distanceMatrix[j + numNodes][i] = -dist;
}
}
// Adăugarea muchiilor de la calculatoare la nodul destinație
for (int i = 1; i <= numNodes; i++) {
adjacencyList[i + numNodes].push_back(targetNode);
adjacencyList[targetNode].push_back(i + numNodes);
capacity[i + numNodes][targetNode] = 1;
}
// Apelarea algoritmului Edmonds-Karp
edmondsKarpAlgorithm();
// Scrierea rezultatului în fișierul de ieșire
outputFile << result;
return 0;
}