Pagini recente » Cod sursa (job #1099472) | Cod sursa (job #415387) | Cod sursa (job #854818) | Cod sursa (job #506596) | Cod sursa (job #2958832)
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;
ifstream in("fmcm.in");
ofstream out("fmcm.out");
int n, m, sursa, destinatie, costMin;
vector<vector<int>> adj;
vector<vector<int>> vCapacitate; //matricea de capacitati (ce flux avem intre 2 noduri)
vector<vector<int>> vCost; //costul unui arc dintre 2 noduri (0 daca nu avem muchie). Pt arcele inverse trecem costul dat cu minus
vector<int> distInit;
vector<int> dist;
vector<int> distActuala;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
bool Dijkstra()
{
int i, currenNode, currenNodeDist, j, newNode, newDist, capacitateMin = INT_MAX, newDest = destinatie, costActual = 0;
vector<int> drum;
drum.clear();
drum.resize(n + 1);
for(i = 1; i <= n; i++)
dist[i] = INT_MAX;
dist[sursa] = 0;
distActuala[sursa] = 0;
pq.push(make_pair(0, sursa));
while(!pq.empty())
{
currenNode = pq.top().second;
currenNodeDist = pq.top().first;
pq.pop();
if(dist[currenNode] == currenNodeDist)
for(j = 0; j < adj[currenNode].size(); j++)
{
newNode = adj[currenNode][j];
if(vCapacitate[currenNode][newNode] > 0) //mai avem capacitate de flux ramasa
{
newDist = dist[currenNode] + vCost[currenNode][newNode] + distInit[currenNode] - distInit[newNode];
if (newDist < dist[newNode])
{
dist[newNode] = newDist;
distActuala[newNode] = distActuala[currenNode] + vCost[currenNode][newNode];
drum[newNode] = currenNode;
pq.push(make_pair(dist[newNode], newNode));
}
}
}
}
for(i = 1; i <= n; i++)
distInit[i] = distActuala[i];
if(dist[destinatie] == INT_MAX) //inseamna ca nu am reusit sa ajungem la destinatie
return false;
while(newDest != sursa)
{
capacitateMin = min(capacitateMin, vCapacitate[drum[newDest]][newDest]);
costActual += vCost[drum[newDest]][newDest];
newDest = drum[newDest];
}
costMin += capacitateMin * distActuala[destinatie];
newDest = destinatie;
while(newDest != sursa)
{
vCapacitate[drum[newDest]][newDest] -= capacitateMin;
vCapacitate[newDest][drum[newDest]] += capacitateMin; //crestem capacitatea ramasa la arcele inverse
newDest = drum[newDest];
}
return true;
}
void BellmanFord()
{
int i, currenNode, j, newNode;
queue<int> coada;
vector<int> inCoada(n + 1, 0); //daca nodul se afla in coada
for(i = 1; i <= n; i++)
distInit[i] = INT_MAX;
distInit[sursa] = 0;
coada.push(sursa);
inCoada[sursa] = 1;
while (!coada.empty())
{
currenNode = coada.front();
coada.pop();
inCoada[currenNode] = 0; //nodul nu mai e in coada pt ca i-am dat pop
for(j = 0; j < adj[currenNode].size(); j++)
{
newNode = adj[currenNode][j];
if(vCapacitate[currenNode][newNode])
if(distInit[currenNode] + vCost[currenNode][newNode] < distInit[newNode]) //e mai ieftin sa ajungem la newNode trecand prin currentNode
{
distInit[newNode] = distInit[currenNode] + vCost[currenNode][newNode];
if (inCoada[newNode] == 0) //daca nu e deja in coada il bagam
{
inCoada[newNode] = 1;
coada.push(newNode);
}
}
}
}
}
int main()
{
int i, nod1, nod2, capacitate, cost;
in >> n >> m >> sursa >> destinatie;
adj.resize(n + 1);
vCapacitate.resize(n + 1);
vCost.resize(n + 1);
dist.resize(n + 1, 0);
distActuala.resize(n + 1, 0);
distInit.resize(n + 1, 0);
for(i = 0; i <= n; i++)
{
vCapacitate[i].resize(n + 1, 0);
vCost[i].resize(n + 1, 0);
}
for (int i = 0; i < m; i++)
{
in >> nod1 >> nod2 >> capacitate >> cost;
adj[nod1].push_back(nod2);
adj[nod2].push_back(nod1);
vCapacitate[nod1][nod2] = capacitate;
vCost[nod1][nod2] = cost;
vCost[nod2][nod1] = -cost; //costul pt arcul invers este minusul costului arcului
}
BellmanFord();
for(;;) //facem dijkstra cat se poate
if(Dijkstra() == false)
break;
out << costMin;
return 0;
}