Cod sursa(job #1967056)

Utilizator SolcanMihaiSolcan Mihai Andrei SolcanMihai Data 15 aprilie 2017 20:42:57
Problema Flux maxim de cost minim Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 3.41 kb
#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
 
using namespace std;
 
const int N = 360;
const int inf = (1 << 27);
 
int n, m, s, d;
int flux[N][N];
int capacitate[N][N];
int cost[N][N];
int oldDist[N];
int dist[N];
int realDist[N];
vector<int> vecini[N];
int sol = 0;
int solx = 0;
int tata[N];
priority_queue<pair<int, int> > Q;  
int inq[N];
 
void citire()
{
    scanf("%d %d %d %d", &n, &m, &s, &d);
    s--;
    d--;
         
    int tmp1, tmp2, tmp3, tmp4;
 
    for(int i = 0; i < m; i++)
    {
        scanf("%d %d %d %d", &tmp1, &tmp2, &tmp3, &tmp4);
 
        tmp1--;
        tmp2--;
 
        vecini[tmp1].push_back(tmp2);
        vecini[tmp2].push_back(tmp1);
        capacitate[tmp1][tmp2] = tmp3;
        cost[tmp1][tmp2] = tmp4;
        cost[tmp2][tmp1] = -tmp4;
    }
}
 
void bellmanFord()
{
    for(int i = 0; i < n; i++)
    {
        oldDist[i] = inf;
    }
 
    queue<int> Q;
 
    Q.push(s);
    oldDist[s] = 0;
    inq[s] = true;
 
    while(Q.empty() == false)
    {
        int x = Q.front();
        inq[x] = false;
 
        Q.pop();
 
        int l = vecini[x].size();
 
        for(int i = 0; i < l; i++)
        {
            if(flux[x][vecini[x][i]] < capacitate[x][vecini[x][i]])
            {
                if(oldDist[vecini[x][i]] <= oldDist[x] + cost[x][vecini[x][i]])  
                {
                    continue;
                }
                oldDist[vecini[x][i]] = oldDist[x] + cost[x][vecini[x][i]];
                if(inq[vecini[x][i]] == true)
                {
                    continue;
                }
                inq[vecini[x][i]] = true;
                Q.push(vecini[x][i]);
            }
        }
    }
}
 
bool dijkstra()
{
    for(int i = 0; i < n; i++)
    {
        dist[i] = inf;
    }
 
    Q.push(make_pair(0, s));
    tata[s] = s;
    dist[s] = 0;
    realDist[s] = 0;
 
    while(Q.empty() == false)
    {
        int x = Q.top().second;
        int y = Q.top().first;
 
        Q.pop();
 
        if(dist[x] != y)
        {
            continue;
        }
 
        int l = vecini[x].size();
 
        for(int i = 0; i < l; i++)
        {
            if(flux[x][vecini[x][i]] < capacitate[x][vecini[x][i]])              
            {
                int z = dist[x] + cost[x][vecini[x][i]] + oldDist[x] - oldDist[vecini[x][i]];
 
                if(dist[vecini[x][i]] > z)
                {
                    dist[vecini[x][i]] = z;
                    realDist[vecini[x][i]] = realDist[x] + cost[x][vecini[x][i]];
                    tata[vecini[x][i]] = x;
                    Q.push(make_pair(dist[vecini[x][i]], vecini[x][i]));
                }
            }
        }
    }
 
    if(dist[d] != inf)
    {
        return true;
    }
 
    return false;
}
 
void solve()
{
    while(dijkstra() == true)
    {
        int valMin = inf;
 
        for(int x = d; x != s; x = tata[x])
        {
            valMin = min(valMin, capacitate[tata[x]][x] - flux[tata[x]][x]);
        }
 
        solx += realDist[d] * valMin;
        sol += valMin;
 
        for(int x = d; x != s; x = tata[x])
        {
            flux[tata[x]][x] += valMin;
            flux[x][tata[x]] -= valMin;
        }

		for(int i = 0; i < n; i++)
		{
			oldDist[i] = realDist[i];
		}
    }
}
 
void afisare()
{
    printf("%d", solx);
}
 
int main()
{
    freopen("fmcm.in", "r", stdin);
    freopen("fmcm.out", "w", stdout);
 
    citire();
    bellmanFord();
    solve();
    afisare();
 
    return 0;
}