Pagini recente » Cod sursa (job #1466083) | Cod sursa (job #1018875) | Cod sursa (job #1437818) | Cod sursa (job #2221830) | Cod sursa (job #2962236)
/*
Taramul Nicaieri https://www.infoarena.ro/problema/harta
Harta "Taramului nicaieri" a fost pierduta, dar din fericire se mai stiu cateva date despre ea. Se stie ca exista N orase intre care se afla diferite drumuri. Drumurile
"Taramului nicaieri" sunt un pic mai ciudate deoarece daca exista un drum care pleaca din orasul i si ajunge in orasul j nu exista in mod obligatoriu si un drum care pleaca din
orasul j si ajunge in orasul i. De asemenea nu vor exista drumuri care pleaca si ajung in acelasi oras. Si nu vor exista mai multe drumuri identice(adica sa coincida si orasul din
care pleaca si cel in care se ajunge).Pentru fiecare oras se stie cate drumuri pleaca din el si cate drumuri ajung in el.
Cerinta
Scrieti un program care determina drumurile de pe harta initiala.
Date de Intrare
Prima linie a fisierului de intrare harta.in contine numarul intreg N, reprezentand numarul de orase. Urmeaza apoi N linii, linia i continand doua numere x,y numarul de drumuri
care pleaca din orasul i respectiv numarul de drumuri care intra in orasul i.
Date de Iesire
In fisierul harta.out veti afisa pe prima linie numarul M de drumuri construite, apoi vor urma M linii pe fiecare aflandu-se o pereche de numere a,b cu semnificatia exista un
drum care pleaca din a si ajunge in b.
*/
#include <fstream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;
int nrOrase, nodInceput, nodSfarsit;
vector<vector <int>> listaAdiacenta, capacitateReziduala;
//functia pentru citirea datelor:
//orasele reprezinta nodurile unui grad orientat, iar pentru determinarea arcelor (drumurilor) pe harta se va calcula fluxul maxim
//pentru a rezolva problema trebuie adaugate doua noduri noi in graf si anume nodul de inceput si nodul de sfasit, de asemenea nodurile care reprezinta orasele se vor dubla, iar fiecare nod din
//multimea initiala de noduri se va lega de toate celelalte dubluri, mai putin de propria dublura
void citire()
{
ifstream fin("harta.in");
fin >> nrOrase;
nodInceput = 0;
nodSfarsit = 2 * nrOrase + 1;
listaAdiacenta.resize(2 * nrOrase + 10);
capacitateReziduala.resize(2 * nrOrase + 10, vector<int>(2 * nrOrase + 10));
for(int i = 1; i <= nrOrase; i++)
for(int j = 1; j <= nrOrase; j++)
if (i != j)
{
listaAdiacenta[i].push_back(j + nrOrase);
listaAdiacenta[j + nrOrase].push_back(i);
capacitateReziduala[i][j + nrOrase] = 1;
}
int gradIntrare, gradIesire;
for (int i = 1; i <= nrOrase; i++)
{
fin >> gradIntrare >> gradIesire;
listaAdiacenta[nodInceput].push_back(i);
listaAdiacenta[i].push_back(nodInceput);
capacitateReziduala[nodInceput][i] = gradIntrare;
listaAdiacenta[nodSfarsit].push_back(i + nrOrase);
listaAdiacenta[i + nrOrase].push_back(nodSfarsit);
capacitateReziduala[i + nrOrase][nodSfarsit] = gradIesire;
}
fin.close();
}
vector<bool> vizitat;
vector <int> tata;
//in cadrul parcurgerii BFS caut lanturi de la nodul de inceput (nodInceput) la nodul final (nodSfarsit) in care fiecare muchie sa aiba capacitatea reziduala mai mica decat capacitatea initiala
bool BFS()
{
tata.clear();
tata.resize(2 * nrOrase + 10, 0);
vizitat.clear();
vizitat.resize(2 * nrOrase + 10, false);
queue<int> vecini;
vecini.push(nodInceput);
vizitat[nodInceput] = true;
tata[nodInceput] = -1;
while (!vecini.empty())
{
int nodCurent = vecini.front();
vecini.pop();
if (nodCurent == nodSfarsit) //am ajuns la nodul de sfasit, asadar am gasit un lant care respecta criteriile impuse, deci ies din structura repetitiva
continue;
for (int vecin : listaAdiacenta[nodCurent])
if (!vizitat[vecin] && capacitateReziduala[nodCurent][vecin] > 0)
{
tata[vecin] = nodCurent;
vecini.push(vecin);
vizitat[vecin] = true;
}
}
return vizitat[nodSfarsit];
}
int fluxMaxim;
void EdmondsKarp()
{
//pentru gasirea drumurilor de ameliorare (drum de la sursa la destinatie, in care fiecare muchie de pe drum sa aiba fluxul asociat pana in acest moment strict mai mic decat capacitatea sa) folosesc parcurgere BFS
//cat timp exista astfel de drumuri de ameliorare, le parcurg, adaugand flux
while (BFS())
{
//penrtu fiecare drum de ameliorare gasit, caut bottleneck-ul (valoarea minima cu care poate fi marit fluxul asociat fiecarei muchii care se afla pe drumul gasit) si updatez capacitatile reziduale
for (int vecin : listaAdiacenta[nodSfarsit])
{
if (vizitat[vecin] && capacitateReziduala[vecin][nodSfarsit] > 0)
{
int fluxCrt = capacitateReziduala[vecin][nodSfarsit];
for (int nodCrt = vecin; nodCrt != nodInceput; nodCrt = tata[nodCrt])
fluxCrt = min(fluxCrt, capacitateReziduala[tata[nodCrt]][nodCrt]);
capacitateReziduala[vecin][nodSfarsit] -= fluxCrt;
capacitateReziduala[nodSfarsit][vecin] += fluxCrt;
for (int nodCrt = vecin; nodCrt != nodInceput; nodCrt = tata[nodCrt])
{
capacitateReziduala[tata[nodCrt]][nodCrt] -= fluxCrt;
capacitateReziduala[nodCrt][tata[nodCrt]] += fluxCrt;
}
fluxMaxim += fluxCrt;
}
}
}
}
void afisare()
{
ofstream fout("harta.out");
fout << fluxMaxim << "\n";
for (int i = 1; i <= nrOrase; i++)
for (int j = nrOrase + 1; j <= 2 * nrOrase; j++)
if (capacitateReziduala[j][i] == 1)
fout << i << " " << j - nrOrase << "\n";
fout.close();
}
int main()
{
citire();
EdmondsKarp();
afisare();
}