Cod sursa(job #1022198)

Utilizator sziliMandici Szilard szili Data 4 noiembrie 2013 21:58:20
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.37 kb
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <limits.h>

using namespace std;

typedef struct node{
    int index;
    int cost;
} NODE;

int n,m,s,d;
vector<int> adjacencyList[351];

int flow[351][351];
int capacities[351][351];
int costs[351][351];
int visited[351];
int prevv[351];
int originalCosts[351];

int smallestDistances[351];
int newSmallestDistances[351];

void relax(int from, int to){

    if (smallestDistances[from] != INT_MAX
        && (smallestDistances[from] + costs[from][to]) < smallestDistances[to]){
            smallestDistances[to] = smallestDistances[from] + costs[from][to];
        }
}

void bellmanFord(){

    for (int i=1; i<=n; i++){
        smallestDistances[i] = INT_MAX;
    }

    smallestDistances[s]=0;

    for (int i=0; i<n-1; i++){

        //take all edges
        for (int from=1; from <= n; from++){
            for (int toIndex=0; toIndex< adjacencyList[from].size(); toIndex++){
                int to = adjacencyList[from][toIndex];

                if (capacities[from][to] - flow[from][to] > 0){
                    relax(from, to);
                }
            }
        }

    }
}


struct cmp_node{
    bool operator() (const NODE &x, const NODE &y){
        return x.cost > y.cost;
    }
};

int dijkstra(int sourceNode){
    priority_queue<NODE, vector<NODE>, cmp_node> q;
    int dijkstraCosts[351];
    int visited[351];

    for (int i=0; i<=n; i++){
        visited[i] = 0;
        dijkstraCosts[i] = INT_MAX;
    }

    NODE n;
    n.index = sourceNode;
    n.cost = 0;

    dijkstraCosts[sourceNode] = 0;
    originalCosts[sourceNode] = 0;

    q.push(n);

    while (!q.empty()){
        NODE currentNode = q.top();
        q.pop();

        if (!visited[currentNode.index]){
            visited[currentNode.index] = 1;

            for (int i=0; i< adjacencyList[currentNode.index].size(); i++){
                int nextNode = adjacencyList[currentNode.index][i];

                if (!visited[nextNode]
                    && capacities[currentNode.index][nextNode] - flow[currentNode.index][nextNode] > 0){

                    int edgeCost = costs[currentNode.index][nextNode] +
                    smallestDistances[currentNode.index] - smallestDistances[nextNode];
                    int costForNewNode = dijkstraCosts[currentNode.index] + edgeCost;

                    if (costForNewNode < dijkstraCosts[nextNode]){
                        dijkstraCosts[nextNode] = costForNewNode;
                        originalCosts[nextNode] = originalCosts[currentNode.index] + costs[currentNode.index][nextNode];
                        prevv[nextNode] = currentNode.index;

                        NODE n2;
                        n2.index = nextNode;
                        n2.cost = costForNewNode;

                        q.push(n2);
                    }
                }
            }
        }
    }

    return visited[d];
}

int main()
{
    freopen("fmcm.in", "r", stdin);
    freopen("fmcm.out", "w", stdout);

    scanf("%d %d %d %d", &n, &m, &s, &d);

    int from, to, capacity, cost;
    for (int i=0; i<m; i++){
        scanf("%d %d %d %d", &from, &to, &capacity, &cost);
        adjacencyList[from].push_back(to);
        adjacencyList[to].push_back(from);

        capacities[from][to] = capacity;
        costs[from][to] = cost;
        costs[to][from] = (-1)*cost;
    }

    bellmanFord();

    //work
    long long sum = 0;
    while (dijkstra(s)){
        for (int i=1; i<=n; i++){
            smallestDistances[i] = originalCosts[i];
        }

        int currentNode = d;
        int minn = INT_MAX;

        while (currentNode != s){
            if (minn > capacities[prevv[currentNode]][currentNode] - flow[prevv[currentNode]][currentNode]){
                minn = capacities[prevv[currentNode]][currentNode] - flow[prevv[currentNode]][currentNode];
            }
            currentNode = prevv[currentNode];
        }

        currentNode = d;

        while (currentNode != s){
            flow[prevv[currentNode]][currentNode] += minn;
            flow[currentNode][prevv[currentNode]] -= minn;


            currentNode = prevv[currentNode];
        }

        sum += minn*smallestDistances[d];
    }

    printf("%lld", sum);

    return 0;
}