Main Topic
A matrix of MXN, given the sh[1,2...m of each row in the matrix, and the number of each column and the SV[1,2...N], and the range limits of some elements in the matrix, such as a[1][2] > 1, a[2][3] < 4, a[3][3] = 10, etc. and requires that each element value in the matrix be non-negative. Find out if there is a matrix that satisfies all the given constraints, if there is an output.
Problem Analysis
So many restrictions: began to think only of the brute force solution + pruning. What the hell does it take to get a brain hole to think of a network flow solution? However, given the idea of network flow after the discovery of the use of network flow solution is really reasonable, very simple (the only bad thing is to build the map too laborious!!) )。
Consider each row as a node, each of which is treated as a node, so that there are M row nodes and N column nodes, a direct path between m and N column nodes, and the traffic on these paths is treated as the element value of the matrix we require.
So how do you use constraints to construct a diagram?
Add a source point S and a meeting point T. The number of each row and the same stream as the upper and lower bounds of the corresponding node from S to the row, and the number of each column and the node that is considered to flow from that column to the same stream as the upper and lower bounds of T .
Then, the range of the matrix element (I, J) is limited to a side representation of the upper and lower bounds of the flow between the row node I to the column node J in the diagram. So, the inflow of row node I (only the s point into the row node) sums up the sum of the numbers for that row, and the row node is connected to n column nodes, and the traffic on the n edges corresponds to the element [i,1][i,2] .... And if there is a feasible flow in the network, we correspond to the sum of the graph node traffic and matrix elements.
Based on the constraints of the matrix element, the graph is constructed as a network stream with a Yuanhui upper and lower bounds. The solution for solving the network feasible flow with the upper and lower bounds of Yuanhui flow is to convert the Yuanhui to no Yuanhui and then solve the feasible flow
。
PS: hemp eggs, wrote for five or six hours, the middle of various bugs, tired feeling no love. Summed up a rule: in the program to solve a number of steps, a variety of factors on a variable, often can summarize the law, do not need each time a factor in action to modify the target variable, you can first the various factors/steps of the impact of recording down, and finally modify the target variable.
In doing so, it is essential to improve efficiency (reducing time complexity and coding complexity, simplifying logic), and sometimes this should be reasonable logic.
Implementation (c + +)
#include <stdio.h> #include <string.h> #include <queue> #include <algorithm>using namespace std ; #define Max_node 250#define max_edge_num 50000#define INFINITE 1 << 25#define min (A, b) a<b? A:b#define Max (A, b) a>b? a:b//============================= The following is the ISAP algorithm portion of the search for the maximum network stream =============================struct edge{//defines the edge int from;int To;int w;int next;int Rev;bool operator = = (const pair<int, int>& p) {return from = = P.first && to = = P.S Econd;}}; Edge gedges[max_edge_num];int gedgecount;int gflow[max_node][max_node];int ggap[max_node];int gDist[MAX_NODE];int Ghead[max_node];int gpre[max_node];int Gpath[max_node];int SS, TT, SUM1, sum2, M, N;int Gsource, Gdestination;void Insert Edge (int u, int v, int w) {edge* it = find (gedges, Gedges + Gedgecount, Pair<int, int> (U, v)); if (it! = gedges + GEDG Ecount) {if (U = = SS | | v = = TT) {it->w + = W;} Else{it->w = w;}} Else{int e1 = Gedgecount;gedges[e1].from = U;gedges[e1].to = V;GEDGES[E1].W = W;gedgeS[e1].next = Ghead[u];ghead[u] = e1;gedgecount++;int E2 = Gedgecount;gedges[e2].from = V;gedges[e2].to = U;GEDGES[E2].W = 0;gedges[e2].next = Ghead[v];ghead[v] = E2;gedges[e1].rev = E2;gedges[e2].rev = e1;gedgecount++;}} void Bfs () {memset (ggap, 0, sizeof (GGAP)), memset (Gdist,-1, sizeof (gdist)); ggap[0] = 1;gdist[gdestination] = 0;queue< int>q; Q.push (gdestination); while (! Q.empty ()) {int n = q.front (); Q.pop (); for (int e = ghead[n]; E! =-1; e = gedges[e].next) {int v = gedges[e].to;if (Gdist[v] >= 0) Continue;gdist[v] = Gdist[n] + 1;ggap[gdist[v]] + +; Q.push (v);}} int ISAP (int n) {//n is the number of nodes BFS (); int u = gsource;int E, d;int ans = 0;while (Gdist[gsource] <= N) {if (U = = gdestination ) {//augmented int min_flow = infinite;for (e = Gpath[u]; u = gsource; e = Gpath[u = Gpre[u]]) {//Note, u = gpre[u], then E = Gpath[u ]min_flow = min (Min_flow, GEDGES[E].W);} U = gdestination;for (e = Gpath[u]; u = gsource; e = Gpath[u = Gpre[u]]) {GEDGES[E].W-= MIN_FLOW;GEDGES[GEDGES[E].REV].W + = Min_flow;gflow[gpre[U]] [u] + = Min_flow;gflow[u][gpre[u]]-= Min_flow; This can not be less, note!!! }ans + = Min_flow;} for (e = Ghead[u]; E! =-1; e = gedges[e].next) {if (gedges[e].w > 0 && gdist[u] = = Gdist[gedges[e].to] + 1) Brea K;} if (e >= 0) {//forward gpre[gedges[e].to] = u;//previous point gpath[gedges[e].to] = e;//The first edge of the point connection U = gedges[e].to;} Else{d = n;for (e = ghead[u]; E! =-1; e = gedges[e].next) {if (gedges[e].w > 0)//need to be able to walk generalist line!! d = min (d, gdist[gedges[e].to]);} if (--ggap[gdist[u]] = = 0)//gap optimization Break;gdist[u] = d + 1;//re-label ++ggap[gdist[u]];//update gap!! if (U = gsource) u = gpre[u];//backtracking}}return ans;} ================================= above for the ISAP algorithm ============================//print out the diagram for debugvoid print_graph (int n) { for (int u = 0; u < n; u++) {printf (' node%d links to ', u); for (int e = Ghead[u]; E! =-1; E = gedges[e].next) printf ("%d (flow =%d)", Gedges[e].to, GEDGES[E].W);p rintf ("\ n");}} The range of numbers in column J of row i is preserved struct node{int min_val;int max_val;}; Node gnodes[250][25];//sets the range of numbers bool Setdatacons (node& Node, char op, INT Val) {if (op = = ' = ') {if (Node.max_val! =-1 && node.max_val < val) {return false;} if (node.min_val! =-1 && node.min_val > val) {return false;} Node.max_val = Node.min_val = val;} else if (op = = ' > ') {if (Node.max_val! =-1 && node.max_val <= val) {return false;} Node.min_val = Max (Node.min_val, Val + 1);} else if (op = = ' < ') {if (val <= 0) {return false;} if (node.min_val! =-1 && node.min_val >= val) {return false;} if (node.max_val! =-1) node.max_val = min (node.max_val, val-1); elsenode.max_val = Val-1;} return true;} build void Buildgraph () {//note, line I, column J, corresponding to the node struct's gnodes[i][j], and corresponding, nodes in the last graph are I and j+m (M is the number of rows) for (int i = 1; I <= m; i++) {for (int j = 1; J <= N; j + +) {if (Gnodes[i][j].max_val = =-1) {if (Gnodes[i][j].min_val = =-1) {Insertedge (i, J + M, INFINITE);} Else{sum1 + = Gnodes[i][j].min_val;insertedge (i, TT, gnodes[i][j].min_val); Insertedge (SS, J + M, Gnodes[i][j].min_val) ; Insertedge (I, J + M, INFINITE); Gflow[i][j + m] = Gnodes[i][j].min_The lower bound of the val;//edge, first joined to the last edge of the traffic}}else {if (Gnodes[i][j].min_val = =-1) {Insertedge (i, J + M, Gnodes[i][j].max_val);} Else{sum1 + = Gnodes[i][j].min_val;insertedge (i, TT, gnodes[i][j].min_val); Insertedge (SS, J + M, Gnodes[i][j].min_val); if (Gnodes[i][j].max_val > Gnodes[i][j].min_val) Insertedge (i, J + M, Gnodes[i][j].max_val-gnodes[i][j].min_val); Gflow[i][j + m] = lower bound of gnodes[i][j].min_val;//edge, first added to the last edge of traffic}}}}}int main () {int C, W, u, V, CAs, Val;char op;scanf ("%d", &am P;cas); while (CAS--) {scanf ("%d%d", &m, &n), memset (Gnodes,-1, sizeof (gnodes)); gedgecount = 0;memset (gedges, 0, sizeof (gedges)); memset (gflow, 0, sizeof (gflow)), memset (Ghead,-1, sizeof (Ghead)); gsource = 0, gdestination = n + M + 1;ss = n + M + 2, TT = n + m + 3;sum1 = 0, sum2 = 0;bool Valid_data = true;//input process, first insert some edges from the SS starting for (int i = 1; I <= m; i + +) {scanf ("%d", &w), if (Valid_data = = False) continue;if (W < 0) {Valid_data = false;} Sum1 + = W;insertedge (ss, I, W);} Insertedge (Gsource, TT, SUM1);//input process, first insert some side to arrive For the TT (int i = m + 1; I <= m + N; i++) {scanf ("%d", &w), if (Valid_data = = False) continue;if (W < 0) Valid_data = False;sum2 + = W;insertedge (i, TT, W);} Insertedge (SS, Gdestination, sum2); if (sum1! = sum2) {Valid_data = false;} Sum1 = Sum2 = (sum1 + sum2);//sets the range of numbers in the Matrix scanf ("%d", &c), for (int i = 0; i < C; i++) {scanf ("%d%d%c", &u, & Amp;v, &op, &val); if (Valid_data = = False) continue;if (W < 0) {if (op = = ' = ' | | op = = ' < ') Valid_data = false; Continue;} if (U = = 0) {if (v = = 0) {for (int i = 1, i <= m; i++) {for (int j = 1; J <= N; j + +) {if (Valid_data = = false) {break;} Valid_data = Setdatacons (Gnodes[i][j],op, Val);}}} else{for (int i = 1; I <= m; i++) {if (Valid_data = = false) {break;} Valid_data = Setdatacons (Gnodes[i][v], op, val);}}} Else{if (v = = 0) {for (int j = 1; J <= N; j + +) {if (Valid_data = = false) {break;} Valid_data = Setdatacons (Gnodes[u][j], op, val);}} Else{valid_data = Setdatacons (Gnodes[u][v], op, val);}}} if (Valid_data = = False) {printf ("IMPossible\n\n "); continue;} Insert the edge of the t-->s, the capacity is infinite, so that the Yuanhui network into a non-Yuanhui network Insertedge (gdestination, Gsource, INFINITE);//Map buildgraph (); gsource = SS; Gdestination = tt;//print_graph (n + M + 4);//find max stream int ans = ISAP (n + M + 4); if (ans! = sum1) {printf ("impossible\n\n"); Conti Nue;} Outputs the traffic for each edge, node I to node J, that is, the size of the number of [i][j-m] in The matrix for (int i = 1; I <= m; i++) {for (int j = m+1; J <= M+n; j + +) {printf ("% D ", Gflow[i][j]);} printf ("\ n");} printf ("\ n");} return 0;}
poj_2396 network flow with upper and lower bounds