A matrix is given with a constraint: I (0 <I <n) rows must at least deploy the number of AI, J rows must be less Bi, and the sum of required values is the smallest.
At first glance, we built a bipartite graph. However, we found that there was a lower bound and no upper bound minimum cost flow problem... Problem conversion: the so-called difficult is opposite! At present, a row/column must have at least K rows and at least the sum. Isn't that row/column having at most K rows and column having the maximum sum? In fact, that is, a maximum of K is used to convert the maximum value into a lower bound of 0, and there is an upper bound of the maximum cost problem (common problem ). The essence of "Fetch" and "not fetch" is the same. It is the idea of "Inaction! If this parameter is specified, the value is the minimum value. If this parameter is not specified, the value is the maximum value. Also. The path is very good, and the name can be very famous ~~
Another point is that, after conversion, the maximum fee may not be the maximum stream. There are two solutions:
First, after each augmented operation, add a judgment. If the cost starts to decrease, it will jump out and get the maximum value at this time. (It is said that the cost of the Bipartite Graph is first increased and then reduced: when the cost is the largest, but the traffic is not the largest at this time, so the cost is reduced to increase the traffic, I don't know if the general graph is ...)
Second: In the release method, all vertices in Part X are directly connected to the edge of the sink. The fee is 0 and the traffic is INF. I feel like this: when there is still traffic in Part X, it is directly released to the sink, all must be the maximum fee (no further reduction ).
I have tried both methods, AC.
# Include <cstdio> # include <iostream> # include <queue> # include <cstring> # include <string> using namespace STD; const int maxv = 200; const int MaxE = 200*200*2 + 800; const int INF = 0x3f3f3f; int nume = 0; int e [MaxE] [4]; int head [maxv]; int n, m; int SS, TT; int Val [105] [105]; void inline Adde (int I, Int J, int C, int W) {e [nume] [0] = J; E [nume] [1] = head [I]; head [I] = nume; E [nume] [2] = C; E [nume ++] [3] = W; E [nume] [0] = I; E [nume] [1] = head [J]; Head [J] = nume; E [nume] [2] = 0; E [nume ++] [3] =-W;} int INQ [maxv]; int pre [maxv]; int PRV [maxv]; int d [maxv]; bool spfa (Int & sum, Int & flow) {for (INT I = 0; I <= tt; I ++) {INQ [I] = 0; d [I] = inf;} queue <int> q; q. push (SS); INQ [ss] = 1; d [ss] = 0; while (! Q. empty () {int cur = Q. front (); q. pop (); INQ [cur] = 0; For (INT I = head [cur]; I! =-1; I = E [I] [1]) {int v = E [I] [0]; if (E [I] [2]> 0 & D [cur] + E [I] [3] <D [v]) {d [v] = d [cur] + E [I] [3]; Pre [v] = I; PRV [v] = cur; If (! INQ [v]) {q. push (V); INQ [v] = 1 ;}}} if (d [TT] = inf) return 0; int cur = tt; int minf = inf; while (cur! = SS) {int Fe = pre [cur]; minf = E [Fe] [2] <minf? E [Fe] [2]: minf; cur = PRV [cur];} cur = tt; while (cur! = SS) {e [pre [cur] [2]-= minf; E [pre [cur] ^ 1] [2] + = minf; cur = PRV [cur];} flow + = minf; sum + = d [TT] * minf; return 1;} int mincost (Int & flow) {int sum = 0; // int lastsum = 0; while (spfa (sum, flow) {; // If (-lastsum>-sum) return lastsum; // obtain the maximum value method // lastsum = sum; // cout <sum <Endl;} return sum;} int sum_all = 0; void Init () {nume = 0; sum_all = 0; SS = N + m; TT = N + m + 1; for (INT I = 0; I <= tt; I ++) head [I] =-1;} void read_build () {(INT I = 0; I <n; I ++) for (Int J = 0; j <m; j ++) {scanf ("% d ", & Val [I] [J]); sum_all + = Val [I] [J]; Adde (I, j + N, 1, -Val [I] [J]);} int AA; For (INT I = 0; I <n; I ++) {scanf ("% d ", & aa); Adde (SS, I, m-AA, 0); Adde (I, TT, M-AA, 0 ); // X directly connects to the vertex edge (enough capacity to release)} For (INT I = 0; I <m; I ++) {scanf ("% d ", & aa); Adde (I + N, TT, N-AA, 0);}/* For (INT I = 0; I <= m + n + 1; I ++) for (Int J = head [I]; J! =-1; j = E [J] [1]) {printf ("% d-> % d: F % DW % d \ n", I, E [J] [0], E [J] [2], E [J] [3]);} */} int main () {int T; cin> T; while (t --) {scanf ("% d", & N, & M); Init (); read_build (); int flow = 0; int ans = sum_all + mincost (flow); printf ("% d \ n", ANS);} return 0 ;}