Matrix sumtime limit: 8000/4000 ms (Java/others) memory limit: 128000/64000 KB (Java/others) submitstatisticnext problemproblem descriptionsweet and zero are playing matrix games, sweet draws an N * M matrix. Each lattice in the matrix has an integer. Zero gives N number Ki, and M number kJ. Zero requires sweet to select some numbers, satisfying at least the number of KI selected from line I, and at least the number of KJ selected in column J. The sum of these values is the number of sweets sweet will pay zero. Sweet wants to know how many sweets he wants to give zero. Can you help him make an optimal strategy? Input
T (t <= 40) indicates the total number of data records, followed by T groups of data.
Data in each group:
N, m (1 <= n, m <= 50)
Next n rows, the number of M in each row (the range is an integer between 0 and)
The next row contains N numbers of KI, indicating that at least the ki elements (0 <= Ki <= m) are selected for row I)
The last row has m quantity KJ, indicating that at least kJ elements (0 <= kJ <= n) are selected in column J)
Output each group of data outputs a row. The minimum number of Sweets that sweet will pay to zero is the sample input.
14 41 1 1 11 10 10 101 10 10 101 10 10 101 1 1 11 1 1 1
Sample output
6
Analysis:
It is easy to think of a bipartite graph model (N rows left endpoint, M columns right endpoint) --> A fee stream with the upper and lower bounds
The number of retrieved data entries in each column in each row cannot be less than R [I]/C [I]. What is the minimum number of retrieved data entries?
Convert
The number of data entries in each column in each row is no more than m-R [I]/n-C [I]. What is the maximum max_sum number obtained?
Min_sum = all_sum-max_sum
Total-maximum charge flow
In this way, the cost flow problem with the upper and lower bound is transformed into a common cost flow problem (only the upper bound.
# Include <cstdio> # include <cstring> # include <queue> # include <vector> # include <algorithm> using namespace STD; const int maxn = 202 + 10; const int INF = 1000000000; typedef long ll; struct edge {int from, to, Cap, flow, cost ;}; struct mcmf {// <span style = "font-size: 14px;"> maximum charge Max stream </span> int n, m, S, T; vector <edge> edges; vector <int> G [maxn]; int INQ [maxn]; // whether int d [maxn] is in the queue // Bellman-Ford int P [Maxn]; // The Last arc int A [maxn]; // improved void Init (int n) {This-> N = N; For (INT I = 0; I <n; I ++) g [I]. clear (); edges. clear ();} void addedge (int from, int to, int cap, int cost) {edges. push_back (edge) {from, to, Cap, 0, cost}); edges. push_back (edge) {to, from, 0, 0,-cost}); M = edges. size (); G [from]. push_back (m-2); G [to]. push_back (m-1);} bool bellmanford (int s, int T, ll & ANS) {for (INT I = 0; I <= T; I ++) d [I] =-INF; // opposite to the maximum minimum charge stream (d [I] = inf) memset (INQ, 0, sizeof (INQ); D [s] = 0; INQ [s] = 1; p [s] = 0; A [s] = inf; queue <int> q; q. push (s); While (! Q. empty () {int u = Q. front (); q. pop (); INQ [u] = 0; For (INT I = 0; I <G [u]. size (); I ++) {edge & E = edges [G [u] [I]; If (E. cap> E. flow & D [E. to] <D [u] + E. cost) {<span style = "font-family: Arial, Helvetica, sans-serif;"> // opposite to the maximum flow with minimum costs (d [E. to] <D [u] + E. cost) </span> d [E. to] = d [u] + E. cost; P [E. to] = G [u] [I]; A [E. to] = min (A [u], E. cap-e. flow); If (! INQ [E. to]) {q. push (E. to); INQ [E. to] = 1 ;}}}if (d [T] <0) return false; // <span style = "font-family: Arial, Helvetica, sans-serif; "> opposite to the maximum flow with minimum cost (d [I]> = 0) </span> ans + = (LL) d [T] * (LL) A [T]; int u = T; while (u! = S) {edges [p [u]. flow + = A [T]; edges [p [u] ^ 1]. flow-= A [T]; u = edges [p [u]. from;} return true;} // you must ensure that the initial network has no negative weight ring ll mincost (int s, int t) {ll cost = 0; while (bellmanford (S, t, cost); Return cost ;}}; mcmf g; int S, T; ll sum; int A [60] [60], R [60], c [60]; void Init () {int n, m, I, j; scanf ("% d", & N, & M); sum = 0; for (I = 1; I <= N; ++ I) for (j = 1; j <= m; ++ J) {scanf ("% d ", & A [I] [J]); sum + = A [I] [J];} for (I = 1; I <= N; ++ I) scanf ("% d", & R [I]); for (I = 1; I <= m; ++ I) scanf ("% d ", & C [I]); s = 0, T = N + m + 1; G. init (t); for (I = 1; I <= N; ++ I) {G. addedge (S, I, m-R [I], 0) ;}for (I = 1; I <= m; ++ I) {G. addedge (I + N, t, n-C [I], 0) ;}for (I = 1; I <= N; ++ I) for (j = 1; j <= m; ++ J) {G. addedge (I, j + N, 1, a [I] [J]) ;}} void solve () {ll T = G. mincost (S, T); printf ("% i64d \ n", Sum-T);} int main () {int t; scanf ("% d ", & T); While (t --) {Init (); solve ();} return 0 ;}
Maximum charge for official question solving
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <queue>using namespace std;const int E = 50010;const int oo = 0x7fffffff;const int N = 210;struct edge{ int next,v,flow,cost;}e[E];int head[N],cnt;queue<int> q;void addedge(int u,int v,int flow,int cost){ e[cnt].v = v; e[cnt].flow = flow; e[cnt].cost = cost; e[cnt].next = head[u]; head[u] = cnt ++;}void addEdge(int u,int v,int flow,int cost){ addedge(u,v,flow,cost); addedge(v,u,0, -cost);}int S,T;int ans;int a[N][N];void init(){ int n,m; scanf("%d%d",&n,&m); ans = 0; for(int i = 1; i <= n; i ++) for(int j = 1; j <= m; j ++) { scanf("%d",&a[i][j]); ans += a[i][j]; } int R[N],C[N]; for(int i = 1; i <= n; i ++) scanf("%d",&R[i]); for(int i = 1; i <= m; i ++) scanf("%d",&C[i]); S = 0,T = n + m + 1; cnt = 0; memset(head,-1,sizeof(head)); for(int i = 1; i <= n; i ++) { addEdge(S,i,m - R[i],0); } for(int i = 1; i <= m; i ++) addEdge(i + n,T,n - C[i],0); for(int i = 1; i <= n; i ++) for(int j = 1; j <= m; j ++) addEdge(i,j + n,1,a[i][j]);}int dis[N],cc[N],visit[N],pre[N],dd[N];int spfa(){ fill(dis,dis + T + 1, -oo); dis[S] = 0; pre[S] = -1; while(!q.empty()) q.pop(); q.push(S); while(!q.empty()) { int u = q.front(); q.pop(); visit[u] = 0; for(int i = head[u]; i != -1; i = e[i].next) { if(e[i].flow > 0 && dis[e[i].v] < dis[u] + e[i].cost) { dis[e[i].v] = dis[u] + e[i].cost; pre[e[i].v] = u; cc[e[i].v] = i; dd[e[i].v] = e[i].cost; if(!visit[e[i].v]) { q.push(e[i].v); visit[e[i].v] = 1; } } } } return dis[T] >= 0;}int argument(){ int aug = oo; int u,v; int ans = 0; for(u = pre[v = T]; v != S; v = u, u = pre[v]) if(e[cc[v]].flow < aug) aug = e[cc[v]].flow; for(u = pre[v = T]; v != S; v = u, u = pre[v]) { e[cc[v]].flow -= aug; e[cc[v] ^ 1].flow += aug; ans += dd[v] * aug; } return ans;}void mcmf(){ memset(visit,0,sizeof(visit)); while(spfa()) { int cost = argument(); if(ans < 0) break; ans -= cost; } printf("%d\n",ans);}int main(){ //freopen("choose.in","r",stdin); //freopen("choose.out","w",stdout); int t; scanf("%d",&t); for(int cas = 1; cas <= t; cas ++) { init(); mcmf(); } return 0;}