zoukankan      html  css  js  c++  java
  • 最小费用流2

    Description
      经典的最小费用最大流问题是这样的。我们需要把一些石油从产油地s运往耗油地t,途中有若干根有向的管道,每根管道有一个容量上限cap,即最多有cap单位的油这根管道经过;每根管道还有一个费用cost,每单位油从这根管道经过需要花费cost的钱。你需要求出在输油量最大的前提下,最少花费多少钱。
      现在我们的有向图如下图。

      每个点没有容量限制,且石油经过点都不需要任何花费。
      图中有4类边。第一类为s到s’的边,其流量为A,费用为0;第二类为s’到xi的边,其容量为Bi,费用为Ci;第三类为xi到yj的边,其容量为Di,j,费用为Ei,j;第四类为yj到t的边,其容量为正无穷,费用为Fj。




    Input
      输入第一行有3个正整数,n,m,A,分别表示图中x类点的个数、y类点的个数和题目叙述中的A。
      第二行有2n个正整数,第2i-1个数和第2i个数(1≤i≤n)表示题目中的Bi和Ci。
      第三行有m个正整数,第j个数(1≤j≤m)表示题目中的Fj。
      接下来n行,每行2m个正整数。第i行(1≤i≤n)第2j-1个数和第2j个数(1≤j≤m)分别表示Di,j和Ei,j。




    Output
      一行两个整数,最大的流量和流量最大时最小的费用。



    Sample Input
    3 2 3
    3 2 2 1 10 2
    1 1
    3 2 3 3
    1 1 3 2
    10 4 10 5



    Sample Output
    3 12



    Hint
      每个测试点的数据规模如下

    qwq ,数据太大 ,用费用流只有70分 ,先附上70分算法 。

      1 #include <iostream>
      2 #include <cstdlib>
      3 #include <cstring>
      4 #include <cstdio>
      5 #include <queue>
      6 const int inf = 1 << 30 , maxn = 2000 + 11 ;//1061109567
      7 using namespace std ;
      8 int n , m , val[maxn][maxn] , vol[maxn][maxn]  , s , t , ans , dis[maxn]  ; 
      9 bool mark[maxn] ;
     10 queue< int > Q ;
     11 
     12 inline void Init( )
     13 {
     14     freopen( "NSOOJ#10829.in" , "r" , stdin ) ;
     15     freopen( "NSOOJ#10829.out" , "w" , stdout )   ;
     16 }
     17 
     18 
     19 
     20 
     21 int read(  ) {
     22     char ch = getchar(  ) ; int ret = 0 , k = 1 ;
     23     while( ch < '0' || ch > '9' ) { if( ch == '-' ) k = -1 ; ch = getchar(  ) ; }
     24     while( ch >= '0' && ch <= '9' ) ret = ret * 10 + ch - '0' , ch = getchar(  ) ;
     25     return ret * k ;
     26 }
     27 
     28 void add( int u , int v , int va , int vo )
     29 {
     30     val[u][v] = va ; vol[u][v] = vo ;
     31 }
     32 
     33 
     34 void input( )
     35 {
     36     n = read( ) , m = read( ) ; 
     37     s = 0 , t =  n + m + 2 ;     
     38     int a = read( )  , b ;
     39     add( s , t - 1 , a , 0 ) ; add( t - 1 , s , 0 , 0 ) ;
     40     for( int x = 1 ; x <= n ; ++x )
     41     {
     42         a = read( ) ; b = read( ) ;
     43         add( t-1 , x , a , b  ) ;
     44         add( x , t-1 , 0 , 0-b ) ;
     45     }
     46     for( int x = 1 ; x <= m ; ++x )
     47     {
     48         a = read( ) ;
     49         add( x+n , t , inf , a ) ;
     50         add( t , x+n , 0 , 0-a ) ;
     51     }
     52     for( int x = 1 ; x <= n ; ++x )
     53         for( int y = 1 ; y <= m ; ++y )
     54         {
     55             a = read( ) , b = read( ) ;
     56             add( x , y+n , a , b ) ;
     57             add( y+n , x , 0 , -b ) ;
     58         }    
     59 }
     60 
     61 bool spfa( )
     62 {
     63     memset( mark , 0 , sizeof( mark ) ) ;
     64     memset( dis , 127/2 , sizeof( dis ) ) ;
     65     mark[t] = 1 , dis[t] = 0 ; Q.push( t ) ;
     66     while( !Q.empty( ) )
     67     {
     68         int u = Q.front( ) ; Q.pop( ) ;
     69         for( int x = s ; x <= t ; x++ )
     70         {
     71             if( val[x][u] && dis[u] + vol[x][u] < dis[x] )
     72             {   
     73                 dis[x] = dis[u] + vol[x][u] ;
     74                 if( !mark[x] )
     75                 {
     76                     Q.push( x ) ;
     77                     mark[x] = true ;
     78                 }
     79             }
     80         }
     81         mark[u] = false ;
     82     } //cout<<endl;
     83     return dis[s] !=1061109567 ;
     84 
     85 }
     86 
     87 int dfs( int x , int f )
     88 {
     89     mark[x] = true ;
     90     if( x == t ) return f ;
     91     int w , used = 0 ;
     92     for( int v = 0 ; v <= t ; ++v )
     93     {
     94         if( dis[v] == dis[x] - vol[x][v] && val[x][v] && !mark[v]  )
     95         {
     96             w = f - used ;
     97             w = dfs( v , min( w , val[x][v] ) ) ;
     98             ans += w * vol[x][v] ;
     99 //            cout<<w<<" "<<x<<" "<<v<<endl;
    100             val[x][v] -= w , val[v][x] += w , used += w ;
    101             if( used == f ) return f ;
    102         }
    103     }
    104     return used ;
    105 }
    106 
    107 
    108 
    109 void zkw( )
    110 {
    111     int sum = 0 ;
    112     while( spfa( ) )
    113     {
    114         mark[t] = 1 ;
    115         while( mark[t] )
    116         {
    117             memset( mark , 0 , sizeof( mark ) ) ;
    118             sum += dfs( s , inf ) ;
    119         }
    120     }
    121     
    122     printf( "%d %d
    " , sum , ans ) ;
    123 }
    124 
    125 
    126 
    127 int main (  )
    128 {
    129 //    Init( ) ;
    130     input( ) ;
    131     zkw( ) ;
    132 //    fclose( stdin ) ;
    133 //    fclose( stdout ) ;
    134     return 0 ;
    135 }

     QwQ正确做法是贪心 ,望天 , 其实还是比较容易想出来的 , 就是将c[i],f[i]加到e[i][j]上去 ,然后排序每次选最少的 ,乘以可行的最大流量 ,然后将b[i]容量减了 ,就行了 ,qwq 。

     1 #include <algorithm>
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <queue>
     7 const int inf = 1 << 30 , maxn = 1000 + 11 ;//1061109567
     8 using namespace std ;
     9 struct id
    10 {
    11     int fro , to , val ;
    12 } edge[maxn*maxn] ;
    13 int n , m , tot , a , b[maxn] , c[maxn] , f[maxn] , d[maxn][maxn] , e[maxn][maxn] ;
    14 
    15 inline void Init( )
    16 {
    17     freopen( "NSOOJ#10829.in" , "r" , stdin ) ;
    18     freopen( "NSOOJ#10829.out" , "w" , stdout )   ;
    19 }
    20 
    21 
    22 
    23 
    24 int read(  ) {
    25     char ch = getchar(  ) ; int ret = 0 , k = 1 ;
    26     while( ch < '0' || ch > '9' ) { if( ch == '-' ) k = -1 ; ch = getchar(  ) ; }
    27     while( ch >= '0' && ch <= '9' ) ret = ret * 10 + ch - '0' , ch = getchar(  ) ;
    28     return ret * k ;
    29 }
    30 
    31 void input( )
    32 {
    33     n = read( ) , m = read( ) ; a = read( ) ;
    34     for( int i = 1 ; i <= n ; ++i ) b[i] = read( ) , c[i] = read( ) ;
    35     for( int i = 1 ; i <= m ; ++i ) f[i] = read( ) ;
    36     for( int i = 1 ; i <= n ; ++i )
    37         for( int j = 1 ; j <= m ; ++j )
    38         {
    39             d[i][j] = read( ) , e[i][j] = read( ) ;
    40             edge[++tot] = (id) { i , j , c[i] + f[j] + e[i][j] } ;
    41         }
    42 }
    43 
    44 int cmp( id  a , id b ) { return a.val < b.val ; }
    45 
    46 
    47 void sov( )
    48 {
    49     sort( edge + 1 , edge + 1 + tot , cmp ) ;
    50     int flow = a ; long long cost = 0 ;
    51     for( int i = 1 ; i <= tot ; ++i )
    52     {
    53         int f = min( flow , min(b[edge[i].fro] , d[edge[i].fro][edge[i].to] ) ) ;
    54         flow -= f ;
    55         b[edge[i].fro] -= f;
    56         cost += 1ll * edge[i].val * f ;
    57     }
    58     printf( "%d %lld
    " , a - flow , cost ) ;
    59 }
    60 
    61 int main (  )
    62 {
    63 //    Init( ) ;
    64     input( ) ;
    65     sov( ) ;
    66 //    fclose( stdin ) ;
    67 //    fclose( stdout ) ;
    68     return 0 ;
    69 }
  • 相关阅读:
    websocket的理解及实例应用
    laravel框架cookie应用到中间件的理解
    PHP多机实现session共享
    mysql中exists的详细说明
    window环境下安装pear
    php 进程管理及操作
    PHP设计模式之职责链模式
    PHP设计模式之备忘录模式
    PHP设计模式之装饰模式
    PHP设计模式之策略模式
  • 原文地址:https://www.cnblogs.com/Ateisti/p/5936085.html
Copyright © 2011-2022 走看看