Cod sursa(job #1076752)

Utilizator fhandreiAndrei Hareza fhandrei Data 10 ianuarie 2014 15:41:03
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 5.74 kb
/*// Include
#include <fstream>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;

// Definitii
#define pb push_back

// Constante
const int sz = 351;
const int oo = 0x3f3f3f3f;

// Functii
bool bellmanFord(int *destDist);

// Variabile
ifstream in("fmcm.in");
ofstream out("fmcm.out");

int nodes, edges, source, destination;
int maxFlow;

int father[sz];

int emptySpace[sz][sz], cost[sz][sz];
vector<int> graph[sz];

// Main
int main()
{
	in >> nodes >> edges >> source >> destination;
	
	int rFrom, rTo, rCapacity, rCost;
	while(edges--)
	{
		in >> rFrom >> rTo >> rCapacity >> rCost;
		graph[rFrom].pb(rTo);
		graph[rTo].pb(rFrom);
		
		emptySpace[rFrom][rTo] = rCapacity;
		
		cost[rFrom][rTo] = rCost;
		cost[rTo][rFrom] = -rCost;
	}
	
	int dist;
	while(bellmanFord(&dist))
	{
		int minFlow = oo;
		
		for(int node=destination ; node!=source ; node=father[node])
			minFlow = min(minFlow, emptySpace[father[node]][node]);
		
		for(int node=destination ; node!=source ; node=father[node])
		{
			emptySpace[father[node]][node] -= minFlow;
			emptySpace[node][father[node]] += minFlow;
		}
		
		maxFlow += dist*minFlow;
	}
	
	out << maxFlow;
	
	in.close();
	out.close();
	return 0;
}

bool bellmanFord(int *destDist)
{
	bool inQueue[sz];
	int dist[sz];
	memset(inQueue, false, sizeof(inQueue));
	memset(father, 0, sizeof(father));
	memset(dist, oo, sizeof(dist));
	
	father[source] = -1;
	dist[source] = 0;
	
	queue<int> bfq;
	bfq.push(source);
	
	while(!bfq.empty())
	{
		int current = bfq.front();
		bfq.pop();
		inQueue[current] = false;
		
		vector<int>::iterator it, end=graph[current].end();
		for(it=graph[current].begin() ; it!=end ; ++it)
		{
			if(!emptySpace[current][*it])
				continue;
			
			if(dist[*it] <= dist[current] + cost[current][*it])
				continue;
			
			dist[*it] = dist[current] + cost[current][*it];
			father[*it] = current;
			
			if(!inQueue[*it])
			{
				bfq.push(*it);
				inQueue[*it] = true;
			}
		}
	}
	
	*destDist = dist[destination];
	return father[destination]? true : false;
}

*/

// Doar n-o sa scrie 70 acolo...

// Include
#include <fstream>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
 
// Definitii
#define pb push_back
#define mp make_pair
 
#define edge pair<int, int>
#define edgeCost first
#define edgeNode second
 
// Constante
const int sz = 351;
const int oo = (1<<30)-1;
 
// Functii
void bellmanFord();
bool dijkstra();
 
// Variabile
ifstream in("fmcm.in");
ofstream out("fmcm.out");
 
bool inQueue[sz];
 
int nodes, edges;
int source, destination;
int minFlowMaxCost;
int father[sz], dist[sz], realDist[sz], oldDist[sz];
int capacity[sz][sz], flow[sz][sz], cost[sz][sz];
 
vector<int> graph[sz];
 
// Main
int main()
{
    in >> nodes >> edges >> source >> destination;
     
    int rFrom, rTo, rCapacity, rCost;
    while(edges--)
    {
        in >> rFrom >> rTo >> rCapacity >> rCost;
        graph[rFrom].pb(rTo);
        graph[rTo].pb(rFrom);
         
        capacity[rFrom][rTo] = rCapacity;
         
        cost[rFrom][rTo] = rCost;
        cost[rTo][rFrom] = -rCost;
    }
     
    bellmanFord();
     
    while(dijkstra())
    {
        int minFlow = oo;
         
        for(int node=destination ; node!=source ; node=father[node])
            minFlow = min(minFlow, capacity[father[node]][node] - flow[father[node]][node]);
         
        for(int node=destination ; node!=source ; node=father[node])
        {
            flow[father[node]][node] += minFlow;
            flow[node][father[node]] -= minFlow;
        }
         
        minFlowMaxCost += minFlow * realDist[destination];
    }
     
    out << minFlowMaxCost << '\n';
     
    in.close();
    out.close();
    return 0;
}
 
void bellmanFord()
{
    for(int i=1 ; i<=nodes ; ++i)
        oldDist[i] = oo;
     
    queue<int> q;
     
    q.push(source);
    inQueue[source] = true;
    oldDist[source] = 0;
     
    while(!q.empty())
    {
        int current = q.front();
        q.pop();
         
        vector<int>::iterator it, end=graph[current].end();
         
        for(it=graph[current].begin() ; it!=end ; ++it)
        {
            if(capacity[current][*it] && oldDist[current]+cost[current][*it] < oldDist[*it])
            {
                oldDist[*it] = oldDist[current]+cost[current][*it];
                if(!inQueue[*it])
                    q.push(*it), inQueue[*it] = true;
            }
        }
        inQueue[current] = false;
    }
}
 
bool dijkstra()
{
    for(int i=1 ; i<=nodes ; ++i)
        dist[i] = oo, father[i] = 0;
     
    priority_queue<edge, vector<edge>, greater<edge> > heap;
     
    dist[source] = 0;
    heap.push(mp(0, source));
     
    while(!heap.empty())
    {
        int current=heap.top().edgeNode;
        if(heap.top().edgeCost != dist[current])
        {
            heap.pop();
            continue;
        }
        heap.pop();
        vector<int>::iterator it, end = graph[current].end();
        for(it=graph[current].begin() ; it!=end ; ++it)
        {
            if(capacity[current][*it] != flow[current][*it] &&
            dist[current] + cost[current][*it] + oldDist[current] - oldDist[*it] < dist[*it])
            {
                dist[*it] = dist[current] + cost[current][*it] + oldDist[current] - oldDist[*it];
                father[*it] = current;
                realDist[*it] = realDist[current] + cost[current][*it];
                heap.push(mp(dist[*it], *it));
            }
        }
    }
     
    for(int i=1 ; i<=nodes ; ++i)
        oldDist[i] = realDist[i];
     
    return father[destination]? 1:0;
}