LOJ6011「网络流 24 题

来源:互联网 发布:明末农民战争史 知乎 编辑:程序博客网 时间:2024/06/03 22:18

大家都很强, 可与之共勉 。

题意:
  W公司有m个仓库和n个零售商店。第i个仓库有ai个单位的货物;第j个零售商店需要 bj个单位的货物。货物供需平衡,即 i=1mai=j=1nbj 。从第 i个仓库运送每单位货物到第j个零售商店的费用为cij​ 。试设计一个将仓库中所有货物运送到零售商店的运输方案,使总运输费用最少。

  然而他要让您输出最小方案和最大方案。

题解:

  她都告诉你了流量平衡……直接就是费用流啊。(会不会给人一种硬点的感觉

  虚拟源点S,和汇点T,然后Sm个仓库,容量为ai,费用为0,仓库和零售店连容量为+,费用为cij的边,然后零售店连T,容量为bj,费用为0

  一遍最小费用最大流,一遍最大费用最大流。

  其实都可以转化为最小费用最大流,对于最大费用,费用变成相反数,就变成了求最小费用最大流,最后答案是相反数。

# 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 16010class  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 ) ;        }} Lazer1 ;class  MaxCostMaxFlow  {    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, -1, sizeof ( int ) * ( T + 1 ) ) ;            Q.push_front ( S ) ;            inq [S] = 1 ;            dis [S] = 0x3f3f3f3f ; // big enough !!!            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 && chkmax ( 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 :        MaxCostMaxFlow ( )  {  ecnt = 1 ; memset ( head, 0, sizeof head ) ;  }        inline void clear ( )  {            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 ) ;        }} Lazer2 ;# undef N# undef Mint main ( )  {    int n, m ;    scanf ( "%d%d", & n, & m ) ;    const int S = n + m + 1, T = n + m + 2 ;    for ( int i = 1 ; i <= n ; ++ i )  {        static int x ;        scanf ( "%d", & x ) ;        Lazer1.add_edge ( S, i, x, 0 ) ;        Lazer2.add_edge ( S, i, x, 0 ) ;    }    for ( int i = 1 ; i <= m ; ++ i )  {        static int x ;        scanf ( "%d", & x ) ;        Lazer1.add_edge ( i + n, T, x, 0 ) ;        Lazer2.add_edge ( i + n, T, x, 0 ) ;    }    for ( int i = 1 ; i <= n ; ++ i )        for ( int j = 1 ; j <= m ; ++ j )  {            static int c ;            scanf ( "%d", & c ) ;            Lazer1.add_edge ( i, j + n, oo, c ) ;            Lazer2.add_edge ( i, j + n, oo, c ) ;        }    printf ( "%d\n%d\n", Lazer1.mcmf ( S, T ).second, Lazer2.mcmf ( S, T ).second ) ;    return 0 ;}