Cod sursa(job #484293)

Utilizator Pepelea_FlaviuFlaviu Pepelea Pepelea_Flaviu Data 13 septembrie 2010 14:43:47
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.09 kb
# include <cstdio>
# include <vector>
# include <queue>
# include <algorithm>

using namespace std;

# define FIN "fmcm.in"
# define FOUT "fmcm.out"

const int MAX_N = 351;
const int MAX_M = 12501;

# define f first
# define s second
# define pb push_back
# define mp make_pair
# define inf 0x3f3f3f3f

queue<int> Q;
int Ap[MAX_N];
int C[MAX_N][MAX_N];
int N, M, S, D, i, j;
vector <pair <int, int> > G[MAX_N];
int Dist[MAX_N], T[MAX_N], H[MAX_N], P[MAX_N];

    inline int min(int A, int B) {
        return A < B ? A : B;
    }

    void Bellman() {
        vector <pair <int, int> > :: iterator it;
        
        memset(Dist, inf, sizeof(Dist));
        Dist[S] = 0; Q.push(S); Ap[S] = 1;
        while (!Q.empty()) {
            Ap[Q.front()] = 0;
            for (it = G[Q.front()].begin(); it != G[Q.front()].end(); ++it) 
               if (Dist[Q.front()] + it -> s < Dist[it -> f] && C[Q.front()][it -> f]) {
                  Dist[it -> f] = Dist[Q.front()] + it -> s;
                  if (!Ap[it -> f]) {
                      Q.push(it -> f);
                      Ap[it -> f] = 1;
                  }
               }
            Q.pop();
        }
    }
    
     void Up(int i) {
         int h = H[i], father = i >> 1, son = i;
         
         while (father && Dist[H[father]] > Dist[h]) {
               H[son] = H[father];
               P[H[father]] = son;
               son = father; father >>= 1;
         }
         
         H[son] = h; P[h] = son;
    }
    
    void Down(int N, int i) {
         int h = H[i], father = i, son = i << 1;
         
         while (son <= N) {
              if (son < N && Dist[H[son]] > Dist[H[son + 1]]) ++son;
              if (Dist[h] > Dist[H[son]]) {
                 H[father] = H[son];
                 P[H[son]] = father;
                 
                 father = son; son <<= 1;
              } else son = N + 1;
         }
         
         H[father] = h; P[h] = father;
    }
    
    bool Dijkstra() {
         int node;
         vector <pair <int, int> > :: iterator it;
         
         for (i = 1; i <= N; ++i)
            for (it = G[i].begin(); it != G[i].end(); ++it)
               if (Dist[i] != inf && Dist[it -> f] != inf)
                  it -> s = Dist[i] - Dist[it -> f] + it -> s;
         
         memset(T, 0, sizeof(T));
         memset(Dist, inf, sizeof(Dist)); Dist[S] = 0;
         for (i = 1; i <= N; ++i) {
             H[i] = i;
             P[i] = i;
         }
         
         H[1] = S; P[S] = 1;
         H[S] = 1; P[1] = S;
         
         for (i = N; i > 1; --i) {
             node = H[1];
             for (it = G[node].begin(); it != G[node].end(); ++it)
                if (Dist[node] + it -> s < Dist[it -> f] && C[node][it -> f]) {
                    T[it -> f] = node;
                    Dist[it -> f] = Dist[node] + it -> s;
                    Up(P[it -> f]);
                }
             H[1] = H[i];
             Down(i - 1, 1);
         }
         
         return Dist[D] == inf ? false : true;
    }
    
    int Flow() {
        int tcost = 0, flow, cur, cost = Dist[D];
        
        while (Dijkstra()) {
              
             for (cur = D, flow = inf; cur != S; cur = T[cur])
                flow = min(flow, C[T[cur]][cur]);
                
             for (cur = D; cur != S; cur = T[cur]) {
                C[T[cur]][cur] -= flow;
                C[cur][T[cur]] += flow;
             }
             
             cost += Dist[D];
             tcost += cost * flow;
        }
        
        return tcost;
    }

    int main() {
        freopen(FIN, "r", stdin);
        freopen(FOUT, "w", stdout);
        
        scanf("%d%d%d%d", &N, &M, &S, &D);
        
        int x, y, c, z;
        for (i = 1; i <= M; ++i) {
            scanf("%d%d%d%d", &x, &y, &c, &z);
            
            C[x][y] = c;
            
            G[x].pb(mp(y, z));
            G[y].pb(mp(x, -z));
        }
        
        Bellman();
        printf("%d\n", Flow());
        
        return 0;
    }