A matrix of N * m is given. Each lattice has a non-negative number, And a number must be selected to maximize the sum. The number in the lattice with adjacent edges cannot be selected at the same time.
First, I never thought about this network stream ...... Because the number of squares (1) is a State compression ......
I understood it after reading the question:
Due to the large data range, the status cannot be compressed. You need to use a network stream:
We know that for a common bipartite graph, the maximum independent point set + the minimum point overwrite set = the total number of points. Similarly, for a right bipartite graph, there are:
Maximum vertex weight independent set + minimum vertex weight overwrite set = total vertex weight,
This question obviously requires the largest vertex weight independent set. Now the total vertex weight is known. We only need to specify the least vertex weight overwrite set. We can create a diagram like this,
1. Perform black and white coloring on the points in the matrix (the adjacent points have different colors) and link an edge from the source point to the Black Point. The weight is the weight of the Black Point,
2. Link an edge from the white point to the sink point. The weight is the weight of the white point,
3. Then, for each adjacent black and white point, an edge is connected from the Black Point to the white point, and the weight is infinite.
Finally, the minimum cut (maximum stream) is obtained, that is, the minimum vertex weight overwrite set.
Because the minimum cut set we have obtained must be selected from the edge between adjacent black and white points (that is, the edge that cannot be used, because the adjacent numbers cannot be selected at the same time, it is the minimum cost, that is, the sum of the numbers removed from the square should be as small as possible, so the sum of the remaining numbers must be the largest.
I can only say that the magic network flow !!!! Orz !!!!
Code:
# Include <cstdio> # include <cstring> # include <queue> # include <cmath> # define find_min (a, B) a <B? A: busing namespace STD; const int n = 2550; const int max = 100000; struct edge {int S, E, V; int next;} edge [20 * n]; int dir [4] [2] = {-, 0,-1,}; int n, m, e_num, head [N], d [N], SP, TP; void addedge (int A, int B, int c) {edge [e_num]. S = A; edge [e_num]. E = B; edge [e_num]. V = C; edge [e_num]. next = head [a]; head [a] = e_num ++; edge [e_num]. S = B; edge [e_num]. E = A; edge [e_num]. V = 0; edge [e_num]. next = head [B]; head [B] = e_num ++ ;} Int judge (int I, Int J, int K) {int II = I + dir [k] [0]; int JJ = J + dir [k] [1]; if (II> = 1 & II <= N & JJ> = 1 & JJ <= m) return 1; return 0;} int BFS () {queue <int> q; memset (D,-1, sizeof (d); D [Sp] = 0; q. push (SP); While (! Q. Empty () {int cur = Q. Front (); q. Pop (); For (INT I = head [cur]; I! =-1; I = edge [I]. next) {int u = edge [I]. e; If (d [u] =-1 & edge [I]. v> 0) {d [u] = d [cur] + 1; q. push (u) ;}} return d [TP]! =-1;} int DFS (int A, int B) {int r = 0; if (a = TP) return B; For (INT I = head [a]; i! =-1 & R <B; I = edge [I]. next) {int u = edge [I]. e; If (edge [I]. v> 0 & D [u] = d [a] + 1) {int x = find_min (edge [I]. v, B-r); X = DFS (u, x); R + = x; edge [I]. v-= x; edge [I ^ 1]. V + = x ;}} if (! R) d [a] =-2; return r;} int dinic (INT sp, int TP) {int Total = 0, T; while (BFS ()) {While (t = DFS (SP, max) Total + = T;} return total;} int main () {int I, J, K, A; while (~ Scanf ("% d", & N, & M) {int sum = 0; e_num = 0; memset (Head,-1, sizeof (head )); SP = 0; TP = N * m + 1; for (I = 1; I <= N; I ++) {for (j = 1; j <= m; j ++) {scanf ("% d", & A); sum + = A; int x = (I-1) * m + J; If (I + J) % 2 = 0) {addedge (SP, X, A); For (k = 0; k <4; k ++) {If (Judge (I, j, k) = 1) {// non-exclusive int y = (I + dir [k] [0]-1) * m + (J + dir [k] [1]); addedge (X, Y, max); // pay attention to the edge direction, yes, black spots are connected to white dots }}else {addedge (x, TP, a); For (k = 0; k <4; k ++) {If (Judge (I, j, k) = 1) {// non-exclusive int y = (I + dir [k] [0]-1) * m + (J + dir [k] [1]); addedge (Y, X, max); // pay attention to the edge direction, opposite to the above }}} int max_flow = dinic (SP, TP); printf ("% d \ n", sum-max_flow);} return 0 ;}