Pagini recente » Cod sursa (job #1554184) | Cod sursa (job #1905698) | Cod sursa (job #249424) | Cod sursa (job #1924359) | Cod sursa (job #552915)
Cod sursa(job #552915)
// http://infoarena.ro/problema/fmcm
#include <fstream>
#include <vector>
#include <queue>
using namespace std;
#define maxSize 351
#define INFINITY 0x3f3f3f3f
ifstream in("fmcm.in");
ofstream out("fmcm.out");
int nodes,edges,source,destination;
int maxFlowMinCost;
bool visit[maxSize];
int dist[maxSize];
int father[maxSize];
int capacity[maxSize][maxSize];
int cost[maxSize][maxSize];
int currentFlow[maxSize][maxSize];
vector<int> graph[maxSize];
bool bellmanFord();
int main() {
in >> nodes >> edges;
in >> source >> destination;
int from,to,flow,currentCost;
for(int i=1;i<=edges;i++) {
in >> from >> to >> flow >> currentCost;
capacity[from][to] = flow;
cost[from][to] = currentCost;
cost[to][from] = -currentCost;
graph[from].push_back(to);
graph[to].push_back(from);
}
// cat timp gasim drumuri de ameliorare
while(bellmanFord()) {
int node;
int minFlow = INFINITY;
// parcurgem invers drumul cu cost minim de la destinatie la sursa
for(node=destination;node!=source;node=father[node])
// calculam valoaream minima cu care putem mari
// fluxul pe acest drum, aceasta fiind valoarea
// minima cu care poate fi marit fluxul asociat
// fiecarei muchii care se afla pe drumul gasit
minFlow = min(minFlow,capacity[father[node]][node] - currentFlow[father[node]][node]);
if(minFlow) {
for(node=destination;node!=source;node=father[node]) {
currentFlow[father[node]][node] += minFlow;
currentFlow[node][father[node]] -= minFlow;
}
maxFlowMinCost += minFlow * dist[destination];
}
}
out << maxFlowMinCost << "\n";
in.close();
out.close();
return (0);
}
bool bellmanFord() {
memset(dist,INFINITY,sizeof(dist));
dist[source] = 0;
memset(visit,false,sizeof(visit));
visit[source] = true;
int node;
vector<int>::iterator it,end;
queue<int> myQueue;
myQueue.push(source);
while(!myQueue.empty()) {
node = myQueue.front();
myQueue.pop();
end = graph[node].end();
for(it=graph[node].begin();it!=end;++it)
// daca fluxul asociat pana in acest moment
// este strict mai mic decat capacitatea
// muchiei iar distanta (costul) este mai mica
if(capacity[node][*it] - currentFlow[node][*it] > 0 && dist[node] + cost[node][*it] < dist[*it]) {
dist[*it] = dist[node] + cost[node][*it]; // actualizam distanta
father[*it] = node; // retinem tatal (pentru reconstructia drumului)
if(!visit[*it]) { // daca nu a fost vizitat
myQueue.push(*it); // il introducem in coada
visit[*it] = true; // il marcam ca vizitat
}
}
visit[node] = false;
}
// daca s-a gasit drum de ameliorare
if(dist[destination] != INFINITY)
return true;
else
return false;
}