#include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; #define COST_t int template class edge{ public: int i, j; COST cost2; V flow; int dest( int from){ if( i == from ) return j; else return i; } COST cost(int from){ if( i == from ) return cost2; else return - cost2; } void flow_add( int from, V r ){ if( i == from ) flow += r; else flow -= r; } }; #define VMAX 100 #define EMAX (2500+VMAX) COST_t d[VMAX]; int prev[VMAX]; int visited[VMAX]; COST_t p[VMAX]; int conn[VMAX]; edge e[EMAX]; int b0[VMAX], b[VMAX]; template COST get_max_flow( int n, const vector< vector< int > > &adj, int m ) { int n1 = n - 1; V bmax = 0; // initial equibilium flow and potential for( int i = n1; i >= 0; -- i ){ b[i] = b0[i]; p[i] = 0; if( b[i] < 0 ) bmax = max( bmax, - b[i] ); else bmax = max( bmax, + b[i] ); } for( int i = m - 1; i >= 0; -- i ) e[i].flow = 0; V delta = 1; while( delta <= (bmax >> 1) ) delta <<= 1; for( ; delta >= 1; delta >>= 1 ){ // until the flow becomes feasible int flag_t = 0, flag_s = 0; for( int i = n1; i >= 0; -- i ){ if( b[i] >= delta ) flag_s ++; else if( b[i] <= -delta ) flag_t ++; } while( flag_t > 0 && flag_s > 0 ){ for( int i = n1; i >= 0; -- i ){ d[i] = INT_MAX; if( b[i] >= delta ) d[i] = 0; } memset( prev, 0xff, sizeof(int)*n ); memset( visited, 0x00, sizeof(int)*n ); int t = -1; while( 1 ){ int i = -1; COST di = INT_MAX; for( int j = n1; j >= 0; -- j ){ if( visited[j] == 0 && d[j] < di ){ i = j; di = d[j]; } } if( i < 0 ) break; visited[i] = 1; if( t < 0 && b[i] <= -delta ) // sink t = i; COST dbase = di + p[i]; for( vector::const_iterator J = adj[i].begin(), JE = adj[i].end(); J != JE; ++ J ){ edge &est = e[*J]; if( est.j == i ){ if( est.flow == 0 ) continue; if( !visited[est.i] ){ COST dj = dbase - est.cost2 - p[est.i]; if( d[est.i] > dj ){ d[est.i] = dj; prev[est.i] = *J; } } } else{ if( !visited[est.j] ){ COST dj = dbase + est.cost2 - p[est.j]; if( d[est.j] > dj ){ d[est.j] = dj; prev[est.j] = *J; } } } } } // dij end if ( t == -1 ) // no feasible flow break; if( d[t] > 0 ){ for( int i = n1; i >= 0; -- i ) p[i] += d[i]; } { V r = -delta; int i, j; for( i = t; (j = prev[i]) >= 0; ){ edge &est = e[j]; if( est.i == i ){ est.flow += r; i = est.j; } else{ est.flow -= r; i = est.i; } } b[t] -= r; b[i] += r; if( b[i] < delta ) flag_s --; if( b[t] > -delta ) flag_t --; } } } COST cost_sum = 0; for( int i = m - 1; i >= 0; -- i ) cost_sum += e[i].cost2 * e[i].flow; return cost_sum; } int main( void ) { vector< vector< int > > adj(VMAX); for( int i = 0; i < VMAX; i ++ ) adj[i].reserve(64); for( int C = 1; ; C ++ ){ int U, V; scanf( "%d%d", &U, &V ); if( U == 0 && V == 0 ) break; int N = U + V; int m = 0; int total = 0; for( int i = 0; i < U; i ++ ){ int j; scanf( "%d", &j ); b0[i] = +j; total += j; } for( int i = 0; i < V; i ++ ){ int j; scanf( "%d", &j ); b0[i+U] = -j; } COST_t maxcost = 0, Mcost = 1; for( int j = N - 1; j >= 0; -- j ) conn[j] = 0; for( int i = 0; i < U; ++ i ) for( int j = U; j < N; ++ j ){ COST_t d; double dd; scanf( "%lf", &dd ); if( dd != -1 ){ d = (COST_t)(dd * 100 + 0.1); maxcost = max( maxcost, d ); edge &est = e[m++]; est.i = i; est.j = j; est.cost2 = d; est.flow = 0; Mcost += d * max( b0[i], -b0[j] ); if( i == 0 ) conn[j] = 1; } } int ne = m; for( int i = U - 1; i >= 1; -- i ){ edge &est = e[m++]; est.i = 0; est.j = i; est.cost2 = Mcost; est.flow = 0; } for( int i = U; i < N; ++ i ){ edge &est = e[m++]; est.i = i; est.j = 0; est.cost2 = Mcost; est.flow = 0; } for( int i = 0; i < N; i ++ ) adj[i].resize(0); for( int i = 0; i < m; i ++ ){ adj[e[i].i].push_back( i ); adj[e[i].j].push_back( i ); } COST_t c1 = get_max_flow( N, adj, m ); for( int i = ne - 1; i >= 0; -- i ) e[i].cost2 = maxcost - e[i].cost2; COST_t c2 = get_max_flow( N, adj, m ) - total * maxcost; printf( "Problem %d: %.2lf to %.2lf\n", C, c1 / 100.0, -c2 / 100.0 ); } return 0; }