P1361 small crop [M] [network flow minimum cut]

Title Description

Small M in the MC opened up two huge farmland A and B (you can think of infinite capacity), now small P n in seed crops, seed crops each have one (is that you can grow a crop ) (with a number 1 ... n).

Now, the i-th crop planted in A revenue available ai and bi planting can get benefits in B, but now there is such an amazing phenomenon that some common types of crops can be cultivated land in one piece obtaining additional revenue, small m found a total of m crop combination rule, the i-th combination of crop species common additional benefits can be obtained c1i in a common total gain additional revenue c2i in B.

Small M quickly calculate the maximum benefit of planting, but he wanted to test you, can you answer his question it?

Input Format

The first line contains an integer n

The second row includes n integer representing ai third row includes n integer representing the fourth row comprising a bi Next integer m m rows,

For the next i-th row: ki first integer, denotes the i th of the total composition crop ki crops,

The next two integers c1i, c2i, ki next integer, indicates the number of crop combination.

Output Format

Only one line, including an integer representing the maximum benefit

Sample input and output

Input # 1
3
4 2 1
2 3 2
1
2 3 2 1 2
Output # 1
11

Description / Tips

Sample interpretation

A farmland species 1,2, B 3 kinds of farmland, revenue 4 + 3 + 2 + 2 = 11.

Data range and Conventions

1 <= k <n <= 1000,0 <m <= 1000 to ensure that all data and the results of not more than 2 * 10 ^ 9.

 

Thinking

  If the crop as an intermediate point, to the source farm A, B to sink.

  Because for each crop can only be planted in a farm, so the problem can be equivalent to a minimum cut model.

  So how to combine the construction side of the bonus is the key.

  The entire assembly is seen as a set of points and point out split into two by a road A to point, and a road from a B to a point, then the point is added successively to be added to the set of points on it.

  This can get the maximum value is the total value - minimum cut

 

CODE

 

  

#include < cstdio >
#include < iostream >
#include < cstring >
#include < queue >
#include < vector >
#include < algorithm >

using  namespace std ;

const  int maxn  =  1 e 6  +  7 ;
const  int inf  =  0x 3f3f3f3f ;

template < class T > inline  void  read(& res )
{
     char c ;T flag = 1 ;
     while((c = getchar()) < ' 0 ' ||c > ' 9 ' )if(c == ' - ' )flag =- 1 ;res =c - ' 0 ' ;
     while((c = getchar()) >= ' 0 ' &&c <= ' 9 ' )res =res * 10 +c - ' 0 ' ;res *=flag ;
}

struct edge { int from ,to ,cap ,flow ;};

struct isap
{
     int n ,s ,t , p [maxn ], d [maxn ], cur [maxn ], num [maxn ];
     bool  vis [maxn ];
    vector <int> g [maxn ];
    vector <edge >edges ;
     void  init( int  n , int  s , int  t )  {
         this -> n  = n ;
         this -> s  = s ;
         this -> t  = t ;
         for( int i  =  1 ;<= n ;i ++ )  g [i ].clear();
         edges .clear();
     }
     void  addegde( int  from , int  to , int  cap )  {
         edges .push_back((edge ){from , to , cap ,  0} );
         edges .push_back((edge ){to , from ,  0 ,  0} );
         int m  =  edges .size();
         g [from ].push_back(m - 2 );
         g [to ].push_back(m - 1 );
     }

     int  augment()  { ///找增广路
         int x  = t ,= inf ;
         while(x !=s )  {
            a  =  min(a ,  edges [ p [x ]]. cap  -  edges [ p [x ]]. flow );
            x  =  edges [ p [x ]]. from ;
         }
        x =t ;
         while(!= s )  {
             edges [ p [x ]]. flow  += a ;
             edges [ p [x ] ^ 1 ]. flow  =  -a ;
            x  =  edges [ p [x ]]. from ;
         }
         return a ;
     }
     int  maxflow()  { ///更新最大流
         int flow  =  0 ;
         memset(num ,  0 ,  sizeof (num ));
         memset(cur ,  0 ,  sizeof (cur ));
         for( int i  =  1 ; i  <= n ; i ++ )  num [ d [i ]] ++ ;
         int x  = s ;
         while( d [s ]  < n )  { ///最长的一条链上,最大的下标是nv-1,如果大于等于nv说明已断层
             if(== t )  {
                flow  +=  augment();
                x  = s ; //回退
             }
             bool ok  =  0 ;
             for( int i  =  cur [x ]; i  <  g [x ].size(); i ++ )  {
                edge  &=  edges [ g [x ][i ]];
                 if( d [x ]  ==  d [ e . to ]  +  1  &&  e . cap  >  e . flow )  {
                     p [ e . to ]  =  g [x ][i ];
                     cur [x ]  = i ;=  e . to ;
                    ok  =  1 ;
                     break;
                 }
             }
             if( !ok )  {
                 int m  = n - 1 ;
                 for( int i  =  0 ; i  <  g [x ].size();i ++ )  {
                    edge  &e = edges [ g [x ][i ]];
                     if( e . cap > e . flow ) m = min(m , d [ e . to ]);
                 }
                 num [ d [x ]] -- ;
                 if( ! num [ d [x ]])  break;
                 d [x ]  = m + 1 ;
                 num [ d [x ]] ++ ;
                 cur [x ]  =  0 ;
                 if(!= s ) x  =  edges [ p [x ]]. from ;
             }
         }
         return flow ;
     }
}ISAP ;

int n , p , q ;
int s , t ;
int tot  =  0 ;
int m ;

int  main()
{
     freopen( " data.txt " ,  " r " , stdin );
     read(n );
    s  = n  +  1 , t  = s  +  1 ;
     ISAP .init(* n , s , t );
     for  (  int i  =  1 ; i  <= n ;  ++)  {
         int x ;  read(x );
        tot  += x ;
         ISAP .addegde(s , i , x );
     }
     for  (  int i  =  1 ; i  <= n ;  ++)  {
         int x ;  read(x );
        tot  += x ;
         ISAP .addegde(i , t , x );
     }   
     read(m );
     for  (  int i  =  1 ; i  <= m ;  ++)  {
         int k ;
         read(k );
         int suma  =  0 , sumb  =  0 ;
         read(suma );  read(sumb );
        tot  += suma  + sumb ;
         ISAP .addegde(s , n  + i  +  2 , suma );
         ISAP .addegde(+ i  + m  +  2 , t , sumb );
         for  (  int j  =  1 ; j  <= k ;  ++)  {
             int x ;
             read(x );
             ISAP .addegde(+  2  + i , x , inf );
             ISAP .addegde(x , n  + i  + m  +  2 , inf );
         }
     }
    //cout << tot << " ! " << ISAP.maxflow() << endl;
     int mincut  =  ISAP .maxflow();
     printf( " %d \n " ,tot  - mincut );
     return  0 ;
}

Guess you like

Origin www.cnblogs.com/orangeko/p/12587338.html
Recommended