Pagini recente » Cod sursa (job #1067880) | Cod sursa (job #2796724) | Cod sursa (job #2890352) | Cod sursa (job #1671753) | Cod sursa (job #1219748)
///FMCM
#include <iostream>
#include <fstream>
#include <vector>
#include <list>
#include <queue>
#include <limits>
using namespace std;
const short INF = numeric_limits<short>::max();
struct Edge {
short to, cost;
Edge(short to, short cost) {
this -> to = to;
this -> cost = cost;
}
};
class CompEdges {
public:
bool operator () (Edge& a, Edge& b) { return a.cost > b.cost; }
};
vector<short> getSignedDistances(vector<list<Edge> >& adjList,
vector<vector<unsigned> >& capacities, short source) {
vector<short> distances(adjList.size(), INF);
vector<bool> inQueue(adjList.size(), false);
queue<short> q;
q.push(source);
distances[source] = 0;
short current;
list<Edge>::iterator it;
while(!q.empty()) {
current = q.front();
q.pop();
inQueue[current] = false;
for(it = adjList[current].begin(); it != adjList[current].end(); it++)
if(capacities[current][it -> to] > 0 &&
distances[current] + it -> cost < distances[it -> to]) {
distances[it -> to] = distances[current] + it -> cost;
if(!inQueue[it -> to]) {
q.push(it -> to);
inQueue[it -> to] = true;
}
}
}
return distances;
}
unsigned getCurrentFlow(vector<vector<unsigned> >& capacities,
vector<short>& previous, short sink) {
unsigned currentFlow = numeric_limits<unsigned>::max();
short prev;
while(previous[sink] > -1) {
prev = previous[sink];
currentFlow = min(currentFlow, capacities[prev][sink]);
sink = prev;
}
return currentFlow;
}
void updateNetwork(vector<vector<unsigned> >& capacities,
vector<short>& previous, short sink, unsigned flow) {
short prev;
while(previous[sink] > -1) {
prev = previous[sink];
capacities[prev][sink] -= flow;
capacities[sink][prev] += flow;
sink = prev;
}
}
int getMinimalCost(vector<list<Edge> >& adjList,
vector<vector<unsigned> >& capacities,
vector<short>& signedDist, short source, short sink) {
int minimalCost = 0;
unsigned currentFlow;
bool isAugmentedPath = true;
while(isAugmentedPath) {
isAugmentedPath = false;
vector<unsigned> modDist(adjList.size(), INF);
vector<int> distances(adjList.size(), INF);
vector<short> previous(adjList.size(), -1);
priority_queue<Edge, vector<Edge>, CompEdges> heap;
modDist[source] = 0;
distances[source] = 0;
heap.push(Edge(source, modDist[source]));
short current;
int currCost;
unsigned modCost;
list<Edge>::iterator it;
while(!heap.empty()) {
current = heap.top().to;
currCost = heap.top().cost;
heap.pop();
if(currCost != modDist[current])
continue;
if(current == sink) {
isAugmentedPath = true;
break;
}
for(it = adjList[current].begin(); it != adjList[current].end(); it++)
if(capacities[current][it -> to] > 0) {
modCost = it -> cost + signedDist[current] - signedDist[it -> to];
if(modCost + modDist[current] < modDist[it -> to]) {
modDist[it -> to] = modCost + modDist[current];
distances[it -> to] = distances[current] + it -> cost;
heap.push(Edge(it -> to, modDist[it -> to]));
previous[it -> to] = current;
}
}
}
if(isAugmentedPath) {
currentFlow = getCurrentFlow(capacities, previous, sink);
updateNetwork(capacities, previous, sink, currentFlow);
minimalCost += distances[sink] * currentFlow;
}
}
return minimalCost;
}
int main() {
ifstream inStr("fmcm.in");
ofstream outStr("fmcm.out");
short numNodes, numEdges, source, sink;
inStr >> numNodes >> numEdges >> source >> sink;
--source; --sink;
vector<list<Edge> > adjList(numNodes);
vector<vector<unsigned> > capacities(numNodes, vector<unsigned>(numNodes, 0));
vector<short> distances(numNodes);
short from, to, cost;
unsigned cap;
for(short i=0; i < numEdges; i++) {
inStr >> from >> to >> cap >> cost;
adjList[--from].push_back(Edge(--to, cost));
adjList[to].push_back(Edge(from, -cost));
capacities[from][to] = cap;
}
distances = getSignedDistances(adjList, capacities, source);
outStr << getMinimalCost(adjList, capacities, distances, source, sink) << '\n';
return 0;
}