Pagini recente » Cod sursa (job #1614293) | Cod sursa (job #1730212) | Cod sursa (job #1692254) | Cod sursa (job #1010883) | Cod sursa (job #3189583)
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;
ifstream f("cc.in");
ofstream g("cc.out");
int main()
{
int n, suma = 0;
f >> n;
// vrem sa facem cuplajul de cost minim => cuplaj + Bellman Ford
// nodurile calculator vor fi de la n + 1 la 2 * n
// nodul 0 = nodul de start
// nodul n * 2 + 1 = nodul de finish
int last = 2 * n + 1;
vector <vector <int>> vecini(last + 1, vector <int> ()); // lista de adiacenta - pt bfs
vector <vector <int>> cost(last + 1, vector <int> (last + 1, 0));
vector <vector <int>> capacitate(last + 1, vector <int> (last + 1, 0));
vector <vector <int>> flux(last + 1, vector <int>(last + 1, 0));
// citim costurile
for(int elev = 1; elev <= n; elev++)
for(int calc = n + 1; calc <= 2 * n; calc++)
{
int cst;
f >> cst;
cost[elev][calc] = cst;
cost[calc][elev] = -cst; // o sa pierd daca aveam selectata muchia si decid sa ma intorc
vecini[elev].push_back(calc);
vecini[calc].push_back(elev);
capacitate[elev][calc] = 1;
}
f.close();
// initializare nod de start
for(int elev = 1; elev <= n; elev++)
{
vecini[elev].push_back(0);
vecini[0].push_back(elev);
capacitate[0][elev] = 1;
}
// initializare nod final
for(int calc = n + 1; calc <= 2 * n; calc++)
{
vecini[calc].push_back(last);
vecini[last].push_back(calc);
capacitate[calc][last] = 1;
}
// alogritmul pentru determinarea fluxului maxim -> vrem sa-l facem cu bellman ford
bool avemDrumDeCrestere = true;
while(avemDrumDeCrestere)
{
avemDrumDeCrestere = false;
//cautam cu bellman ford un lant de cost minim in care sa putem creste fluxul
queue <int> q;
vector <int> tata(last + 1); // tinem tatal fiecarui nod din lant, daca muchia intoarce flux => -tata
//vector <bool> vis(last + 1, false); // vector de vizitati
vector <int> cost_temp(last + 1, INT_MAX); // costuri pt bellman-ford
//initializare vector de tati
for(int i = 0; i <= last; i++)
tata[i] = i;
q.push(0);
//vis[0] = true;
cost_temp[0] = 0;
while(!q.empty())
{
int nod = q.front();
q.pop();
for(int i = 0; i < vecini[nod].size(); i++)
{
int vecin = vecini[nod][i];
//daca pot imbunatati si fluxul si costul
if(capacitate[nod][vecin] > flux[nod][vecin] && cost_temp[vecin] > cost_temp[nod] + cost[nod][vecin])
{
q.push(vecin);
//vis[vecin] = true;
tata[vecin] = nod;
cost_temp[vecin] = cost_temp[nod] + cost[nod][vecin];
// daca am gasit un lant pana la nodul final
if(vecin == last)
{
avemDrumDeCrestere = true;
break;
}
}
}
}
// daca avem drum
if(avemDrumDeCrestere)
{
// il parcurgem si aflam fluxul maxim pe care putem sa-l pusham pe toate muchiile
int nodCurent = last;
int fluxMaxim = 100; // fluxul nostru maxim pe un drum oricum e 1 =)
while(nodCurent != 0)
{
int predecesor = tata[nodCurent];
if(fluxMaxim > capacitate[predecesor][nodCurent] - flux[predecesor][nodCurent])
fluxMaxim = capacitate[predecesor][nodCurent] - flux[predecesor][nodCurent];
nodCurent = predecesor;
}
// il parcurgem si pusham fluxul respectiv pe fiecare muchie
nodCurent = last;
while(nodCurent != 0)
{
int predecesor = tata[nodCurent];
flux[predecesor][nodCurent] += fluxMaxim;
flux[nodCurent][predecesor] -= fluxMaxim;
nodCurent = predecesor;
}
}
}
// vedem ce muchii am folosit pentru a realiza cuplajul + costul lor
for(int elev = 1; elev <= n; elev++)
for(int calc = n + 1; calc <= 2 * n; calc++)
if(flux[elev][calc])
{
suma += cost[elev][calc];
continue;
}
g << suma;
g.close();
return 0;
}