Cod sursa(job #829786)

Utilizator alex_unixPetenchea Alexandru alex_unix Data 5 decembrie 2012 20:50:08
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 2.77 kb
#include <cstdio>
#include <cstring>
#include <vector>
 
const int MAX_SIZE(351);
const int MAX_COST(1 << 30);
const int MAX_CAPACITY(10000);
const int QUEUE_SIZE(1000000);
 
int n, m, source, sink;
long long min_cost;
 
int capacity [MAX_SIZE] [MAX_SIZE];
int cost [MAX_SIZE] [MAX_SIZE];
int queue [QUEUE_SIZE], *pop, *push;
int pred [MAX_SIZE];
int path_cost [MAX_SIZE];
bool mark [MAX_SIZE];

std::vector<int> graph [MAX_SIZE];

inline void read (void)
{
    std::freopen("fmcm.in","r",stdin);
    std::scanf("%d%d%d%d",&n,&m,&source,&sink);
    int x, y, c, z;
    for (int counter(0) ; counter < m ; ++counter)
    {
        std::scanf("%d%d%d%d",&x,&y,&c,&z);
        graph[x].push_back(y);
        graph[y].push_back(x);
        capacity[x][y] = c;
        cost[x][y] = z;
        cost[y][x] = -z;
    }
    std::fclose(stdin);
}
 
inline void print (void)
{
    std::freopen("fmcm.out","w",stdout);
    std::printf("%lld\n",min_cost);
    std::fclose(stdout);
}
 
inline void initialize (void)
{
    for (int index(1) ; index <= n ; ++index)
        path_cost[index] = MAX_COST;
    path_cost[source] = 0;
    pred[source] = 0;
    pred[sink] = 0;
    pop = queue;
    push = queue + 1;
    *queue = source;
}
 
inline void BellmanFord (void)
{
    initialize();
    int vertex, neighbor, size, index;
    while (pop < push)
    {
        vertex = *pop;
        ++pop;
        for (index = 0, size = graph[vertex].size() ; index < size ; ++index)
            if (capacity[vertex][graph[vertex][index]])
            {
                neighbor = graph[vertex][index];
                if (path_cost[vertex] + cost[vertex][neighbor] < path_cost[neighbor])
                {
                    path_cost[neighbor] = path_cost[vertex] + cost[vertex][neighbor];
                    pred[neighbor] = vertex;
                    if (!mark[neighbor])
                    {
                        *push = neighbor;
                        ++push;
                        mark[neighbor] = true;
                    }
                }
            }
        mark[vertex] = false;
    }
}
 
inline void FordFulkerson (void)
{
    int vertex, path_capacity;
    while (true)
    {
        BellmanFord();
        if (!pred[sink])
            break;
        path_capacity = MAX_CAPACITY;
        for (vertex = sink ; vertex != source ; vertex = pred[vertex])
            if (capacity[pred[vertex]][vertex] < path_capacity)
                path_capacity = capacity[pred[vertex]][vertex];
        for (vertex = sink ; vertex != source ; vertex = pred[vertex])
        {
            capacity[pred[vertex]][vertex] -= path_capacity;
            capacity[vertex][pred[vertex]] += path_capacity;
        }
        min_cost += path_cost[sink] * path_capacity;
    }
}
 
int main (void)
{
    read();
    FordFulkerson();
    print();
    return 0;
}