LOJ6013 "Network Flow 24 - 14" Load Balancing Drop Small Cost Drop Flow

Everyone is strong enough to share their support.

Topic:
Company_G has n warehouses arranged in a circular pattern along the railway transport line, each of which stores a different number of goods.How to make the inventory of N warehouses the same with the minimum amount of handling.When carrying goods, they can only be carried between adjacent warehouses.

Questions:
_Find the average value and turn it into a problem of supply and demand.This question is equivalent to supplying warehouses with surplus to warehouses with losses.So the surplus is in one set and the loss is in one set.Note that this problem can be connected between adjacent warehouses, that is, all warehouses can reach each other, but the unit costs are different, so we can easily handle this situation directly in one set.
_For a warehouse with a surplus at source point S after the point of dismantling, the cost is 0, the flow is the surplus, the loss is the warehouse junction T, the cost is 0, and the flow is the absolute value of the loss.Then the cost of connection between adjacent points on the left side is 1, and the flow rate is + (+ only for transshipment of goods).The cost of connecting the points on the left to the right (between adjacent neighbors) is 1, and the flow rate is +.(for supply)

_Then run the minimum cost, the maximum flow.

# include <bits/stdc++.h>

template < class T >  inline bool chkmax ( T& d, const T& x )  {  return d < x ? ( d = x ), 1 : 0 ;  }
template < class T >  inline bool chkmin ( T& d, const T& x )  {  return d > x ? ( d = x ), 1 : 0 ;  }

# define oo 0x3f3f3f3f

# define N 5010
# define M 16010

class  MinCostMaxFlow  {
    private :
        struct edge  {
            int to, nxt, w, cost ;
        } g [M << 1] ;

        int S, T ;
        int head [N], dis [N], pre [N], ecnt ;

        inline bool spfa ( int S, int T )  {
            static std :: bitset < N > inq ;
            static std :: deque < int > Q ;
            inq.reset ( ) ; Q.clear ( ) ;
            memset ( pre, 0, sizeof ( int ) * ( T + 1 ) ) ;
            memset ( dis, 0x3f, sizeof ( int ) * ( T + 1 ) ) ;
            Q.push_front ( S ) ;
            inq [S] = 1 ;
            dis [S] = 0 ;
            while ( ! Q.empty ( ) )  {
                int u = Q.front ( ) ; Q.pop_front ( ) ;
                inq [u] = 0 ;
                for ( int i = head [u] ; i ; i = g [i].nxt )  {
                    int& v = g [i].to ;
                    if ( g [i].w && chkmin ( dis [v], dis [u] + g [i].cost ) )  {
                        pre [v] = i ;
                        if ( ! inq [v] )  {
                            ( Q.empty ( ) || dis [v] < dis [Q.front ( )] ) ? Q.push_front ( v ) : Q.push_back ( v ) ;
                            inq [v] = 1 ;
                        }
                    }
                }
            }
            return ( bool ) pre [T] ;
        }
    public :
        MinCostMaxFlow ( )  {  ecnt = 1 ; memset ( head, 0, sizeof head ) ;  }

        inline void add_edge ( int u, int v, int w, int cost )  {
            g [++ ecnt] = ( edge )  {  v, head [u], w, cost } ; head [u] = ecnt ;
            g [++ ecnt] = ( edge )  {  u, head [v], 0, -cost } ; head [v] = ecnt ;
        }

        std :: pair < int, int > mcmf ( int S, int T )  {
            this -> S = S, this -> T = T ;
            int flow = 0, cost = 0, x ;
            while ( spfa ( S, T ) )  {
                x = oo ;
                for ( int i = pre [T] ; i ; i = pre [g [i ^ 1].to] )  chkmin ( x, g [i].w ) ;
                for ( int i = pre [T] ; i ; i = pre [g [i ^ 1].to] )  {
                    g [i].w -= x, g [i ^ 1].w += x ;
                    cost += x * g [i].cost ;
                }

                flow += x ;
            }
            return std :: make_pair ( flow, cost ) ;
        }
} Lazer ;

int a [N] ;

# undef N
# undef M

int main ( )  {
    int n ;
    scanf ( "%d", & n ) ;
    const int S = n + n + 1, T = n + n + 2 ;
    int sum ( 0 ) ;

    for ( int i = 1 ; i <= n ; ++ i )  scanf ( "%d", a + i ) ;
    for ( int i = 1 ; i <= n ; ++ i )  sum += a [i] ;

    int ave = sum / n ;

    for ( int i = 1 ; i <= n ; ++ i )  a [i] -= ave ;

    for ( int i = 1 ; i <= n ; ++ i )  {
        if ( a [i] > 0 )  Lazer.add_edge ( S, i, a [i], 0 ) ;
        else  Lazer.add_edge ( i + n, T, - a [i], 0 ) ;
        Lazer.add_edge ( i, ( ( i + 1 ) > n ? i + 1 - n : i + 1 ) + n, oo, 1 ) ;
        Lazer.add_edge ( i, ( ( i + 1 ) > n ? i + 1 - n : i + 1 ), oo, 1 ) ;
        Lazer.add_edge ( i, ( ( i - 1 ) < 1 ? i - 1 + n : i - 1 ) + n, oo, 1 ) ;
        Lazer.add_edge ( i, ( ( i - 1 ) < 1 ? i - 1 + n : i - 1 ), oo, 1 ) ;
    }

    printf ( "%d\n", Lazer.mcmf ( S, T ).second ) ;

    return 0 ;
}

Posted on Fri, 03 Jul 2020 10:26:44 -0400 by ankurcse