Cod sursa(job #2253948)

Utilizator akumariaPatrascanu Andra-Maria akumaria Data 4 octombrie 2018 16:40:40
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 3.72 kb
#include <cstdio>
#include <cstring>
#include <queue>

#define MAXN 352
#define INF 13000000

using namespace std;


int n, m, source, dest;
int flux, fcost;

priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > pq;
vector<int> arcs[MAXN];
int costs[MAXN][MAXN];
int caps[MAXN][MAXN];

int bf_res[MAXN];


void bellman_ford()
{
    int curr_node;
    int viz[n+1], i, next_node;
    queue<int> q;

    memset(viz, 0, sizeof(viz));
    memset(bf_res, INF, sizeof(bf_res));

    q.push(source);
    viz[source] = 1;
    bf_res[source] = 0;

    while(!q.empty())
    {
        curr_node = q.front();
        viz[curr_node] = 0;

        for(i = 0; i<arcs[curr_node].size(); ++i)
            if(caps[curr_node][arcs[curr_node][i]])
            {
                next_node = arcs[curr_node][i];
                if(bf_res[curr_node] + costs[curr_node][next_node] >= bf_res[next_node])
                    continue;

                bf_res[next_node] = bf_res[curr_node] + costs[curr_node][next_node];

                if (!viz[next_node])
                {
                    viz[next_node] = 1;
                    q.push(next_node);
                }
            }

        q.pop();
    }
}


bool dijkstra()
{
    int i, next_node, next_cost, curr_node;
    int d_working[n+2], d_final[n+2], parents[n+2], d_old[n+2];
    memset(d_working, INF, sizeof(d_working));
    memset(d_final, 0, sizeof(d_final));
    memset(parents, 0, sizeof(parents));

    memcpy(d_old, bf_res, sizeof(d_final));

    d_working[source] = d_final[source] = 0;
    pq.push(make_pair(d_working[source], source));

    while (!pq.empty())
    {
        int curr_cost = pq.top().first;
        int curr_node = pq.top().second;
        pq.pop();

        if (d_working[curr_node] != curr_cost)
            continue;

        for (i=0; i<arcs[curr_node].size(); ++i)
            if(caps[curr_node][arcs[curr_node][i]])
            {
                next_node = arcs[curr_node][i];
                next_cost = d_working[curr_node] + costs[curr_node][next_node] +
                                d_old[curr_node] - d_old[next_node];

                if (next_cost < d_working[next_node])
                {
                    d_working[next_node] = next_cost;
                    d_final[next_node] = d_final[curr_node] + costs[curr_node][next_node];
                    parents[next_node] = curr_node;
                    pq.push(make_pair(next_cost, next_node));
                }
            }
    }

    if(!parents[dest])
        return false;

    memcpy(d_old, d_final, sizeof(d_working));

    int minf = INF, mincost = 0;
    for(curr_node = dest; curr_node != source; curr_node = parents[curr_node])
    {
        if(minf > caps[parents[curr_node]][curr_node])
            minf = caps[parents[curr_node]][curr_node];
        mincost += costs[parents[curr_node]][curr_node];
    }

    flux += minf;
    fcost += minf * d_final[dest];

    for(curr_node = dest; curr_node != source; curr_node = parents[curr_node])
    {
        caps[parents[curr_node]][curr_node] -= minf;
        caps[curr_node][parents[curr_node]] += minf;
    }


    return true;
}


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

    int x, y;
    scanf("%d%d%d%d", &n, &m, &source, &dest);

    for(int i=0; i<m; ++i)
    {
        scanf("%d%d", &x, &y);
        arcs[x].push_back(y);
        arcs[y].push_back(x);

        scanf("%d%d", &caps[x][y], &costs[x][y]);
        costs[y][x] = -costs[x][y];
    }

    bellman_ford();
    while(dijkstra());

    printf("%d\n", fcost);

    fclose(stdin);
    fclose(stdout);
    return 0;
}