1
+ import java .util .ArrayDeque ;
2
+ import java .util .Arrays ;
3
+ import java .util .Queue ;
4
+
5
+ public class Solution2123 {
6
+ public int minimumOperations (int [][] grid ) {
7
+ int m = grid .length ;
8
+ int n = grid [0 ].length ;
9
+ int id = 1 ;
10
+ for (int i = 0 ; i < m ; i ++) {
11
+ for (int j = 0 ; j < n ; j ++) {
12
+ if (grid [i ][j ] == 1 ) grid [i ][j ] = id ++;
13
+ }
14
+ }
15
+
16
+ int S = id ++;
17
+ int T = id ++;
18
+ MaxFlow maxFlow = new MaxFlow (S , T );
19
+
20
+ for (int i = 0 ; i < m ; i ++) {
21
+ for (int j = 0 ; j < n ; j ++) {
22
+ if (grid [i ][j ] == 0 ) continue ;
23
+ int x = grid [i ][j ];
24
+ if (i - 1 >= 0 && grid [i - 1 ][j ] > 0 ) {
25
+ int y = grid [i - 1 ][j ];
26
+ // 偶数到奇数连 1
27
+ if ((i + j ) % 2 == 0 ) maxFlow .add (x , y , 1 );
28
+ else maxFlow .add (y , x , 1 );
29
+ }
30
+ if (j - 1 >= 0 && grid [i ][j - 1 ] > 0 ) {
31
+ int y = grid [i ][j - 1 ];
32
+ // 偶数到奇数连 1
33
+ if ((i + j ) % 2 == 0 ) maxFlow .add (x , y , 1 );
34
+ else maxFlow .add (y , x , 1 );
35
+ }
36
+ if ((i + j ) % 2 == 0 ) maxFlow .add (S , x , 1 );
37
+ else maxFlow .add (x , T , 1 );
38
+ }
39
+ }
40
+ return (int ) maxFlow .maxflow ();
41
+ }
42
+
43
+ static class MaxFlow {
44
+ int inf = 1 << 29 , N = 100010 , M = 600010 ;
45
+ int [] head = new int [N ], ver = new int [M ], edge = new int [M ], Next = new int [M ], d = new int [N ];
46
+ int n , m , s , t , tot ;
47
+ long maxflow ;
48
+ Queue <Integer > q ;
49
+
50
+ public MaxFlow (int s , int t ) {
51
+ this .s = s ;
52
+ this .t = t ;
53
+ this .tot = 1 ;
54
+ }
55
+
56
+ void add (int x , int y , int z ) {
57
+ ver [++tot ] = y ;
58
+ edge [tot ] = z ;
59
+ Next [tot ] = head [x ];
60
+ head [x ] = tot ;
61
+
62
+ ver [++tot ] = x ;
63
+ edge [tot ] = 0 ;
64
+ Next [tot ] = head [y ];
65
+ head [y ] = tot ;
66
+ }
67
+
68
+ boolean bfs () { // 在残量网络上构造分层图
69
+ Arrays .fill (d , 0 );
70
+ while (!q .isEmpty ()) q .remove ();
71
+ q .add (s );
72
+ d [s ] = 1 ;
73
+ while (!q .isEmpty ()) {
74
+ int x = q .remove ();
75
+ for (int i = head [x ]; i != 0 ; i = Next [i ]) {
76
+ if (edge [i ] != 0 && d [ver [i ]] == 0 ) {
77
+ q .add (ver [i ]);
78
+ d [ver [i ]] = d [x ] + 1 ;
79
+ if (ver [i ] == t ) return true ;
80
+ }
81
+ }
82
+ }
83
+ return false ;
84
+ }
85
+
86
+ int dinic (int x , int flow ) { // 在当前分层图上增广
87
+ if (x == t ) return flow ;
88
+ int rest = flow , k ;
89
+ for (int i = head [x ]; i != 0 && rest != 0 ; i = Next [i ]) {
90
+ if (edge [i ] != 0 && d [ver [i ]] == d [x ] + 1 ) {
91
+ k = dinic (ver [i ], Math .min (rest , edge [i ]));
92
+ if (k == 0 ) d [ver [i ]] = 0 ; // 剪枝,去掉增广完毕的点
93
+ edge [i ] -= k ;
94
+ edge [i ^ 1 ] += k ;
95
+ rest -= k ;
96
+ }
97
+ }
98
+ return flow - rest ;
99
+ }
100
+
101
+ long maxflow () {
102
+ q = new ArrayDeque <>();
103
+ long flow ;
104
+ while (bfs ()) {
105
+ while ((flow = dinic (s , inf )) != 0 ) maxflow += flow ;
106
+ }
107
+ return maxflow ;
108
+ }
109
+ }
110
+ }
111
+ /*
112
+ 2123ドル. 使矩阵中的 1 互不相邻的最小操作数
113
+ https://leetcode.cn/problems/minimum-operations-to-remove-adjacent-ones-in-matrix/description/
114
+
115
+ 给你一个 下标从 0 开始 的矩阵 grid。每次操作,你可以把 grid 中的 一个 1 变成 0 。
116
+ 如果一个矩阵中,没有 1 与其它的 1 四连通(也就是说所有 1 在上下左右四个方向上不能与其他 1 相邻),那么该矩阵就是 完全独立 的。
117
+ 请返回让 grid 成为 完全独立 的矩阵的 最小操作数。
118
+ 提示:
119
+ m == grid.length
120
+ n == grid[i].length
121
+ 1 <= m, n <= 300
122
+ grid[i][j] 是 0 或者 1.
123
+
124
+ 二分图最大匹配,由于 O(nm) 会 TLE。
125
+ 该用 Dinic 最大流来求。
126
+ 时间复杂度 O(sqrt(n) * m)。
127
+ */
0 commit comments