方格取数问题,最小割模型~

View Code
1 #include <cstdio>
2 #include <cstring>
3
4  using namespace std;
5
6  const int maxN = 64;
7 const int INF = (1 << 30);
8 const int dx[] = { -1, 0, 1, 0 };
9 const int dy[] = { 0, 1, 0, -1 };
10
11 class Network {
12 private:
13 const static int MAXV = 10240; // ¶¥µãÊý
14 const static int MAXE = 100000; // ±ßÊý * 2
15
16 struct List {
17 int v;
18 int f;
19 List * rev;
20 List * next;
21 };
22
23 List pool[MAXE];
24 List * path[MAXV];
25 List * head[MAXV];
26 List * cur[MAXV];
27 List * pp;
28
29 int n;
30 int s;
31 int t;
32 int dist[MAXV];
33 int num[MAXV];
34 int pred[MAXV];
35
36 inline List * create(int v, int f, List * next) {
37 pp->v = v;
38 pp->f = f;
39 pp->next = next;
40 return pp++;
41 }
42
43 void InitDist();
44 int Augment(int &);
45 public:
46 void Init(int nv, int ss, int tt);
47 void addEdge(int u, int v, int f);
48 int maxFlow();
49 };
50
51 void Network::Init(int nv, int ss, int tt) {
52 int i;
53
54 n = nv;
55 s = ss;
56 t = tt;
57
58 pp = pool;
59 memset(head, 0, n * sizeof(head[0]));
60 memset(cur, 0, n * sizeof(cur[0]));
61 memset(num, 0, n * sizeof(int));
62
63 pred[s] = -1;
64
65 for (i = 0; i < n; i++)
66 dist[i] = n;
67
68 return;
69 }
70
71 void Network::addEdge(int u, int v, int f) {
72 head[u] = create(v, f, head[u]);
73 head[v] = create(u, 0, head[v]);
74
75 head[u]->rev = head[v];
76 head[v]->rev = head[u];
77
78 return;
79 }
80
81 void Network::InitDist() {
82 int queue[MAXV];
83 int qh = -1;
84 int qe = 0;
85
86 List * p;
87
88 dist[t] = 0;
89 queue[0] = t;
90
91 while (qh != qe) {
92 qh++;
93 int u = queue[qh];
94 for (p = head[u]; p; p = p->next)
95 if (p->f == 0 && dist[p->v] == n) {
96 dist[p->v] = dist[u] + 1;
97 num[dist[p->v]]++;
98 queue[++qe] = p->v;
99 }
100 }
101
102 return;
103 }
104
105 int Network::Augment(int & sum) {
106 int u;
107 int last = s;
108 int minl = INF;
109
110 for (u = t; u != s; u = pred[u])
111 minl = minl < path[u]->f ? minl : path[u]->f;
112 sum += minl;
113 for (u = t; u != s; u = pred[u]) {
114 path[u]->f -= minl;
115 path[u]->rev->f += minl;
116 if (path[u]->f == 0)
117 last = pred[u];
118 }
119
120 return last;
121 }
122
123 int Network::maxFlow() {
124 bool update;
125 int u = s;
126 int ret = 0;
127
128 List * p;
129
130 InitDist();
131 memcpy(cur, head, sizeof(head));
132
133 while (dist[s] < n) {
134 update = false;
135 for (p = cur[u]; p; p = p->next)
136 if (dist[p->v] + 1 == dist[u] && p->f > 0) {
137 update = true;
138 pred[p->v] = u;
139 path[p->v] = p;
140 cur[u] = p;
141 u = p->v; // Ç°œø²œ
142 if (u == t)
143 u = Augment(ret);
144 break;
145 }
146 if (!update) {
147 if (--num[dist[u]] == 0) // Œä϶ÓÅ»¯
148 break;
149 cur[u] = head[u];
150 dist[u] = n;
151 for (p = head[u]; p; p = p->next) // ÖرêºÅ
152 if (p->f > 0 && dist[u] > dist[p->v] + 1)
153 dist[u] = dist[p->v] + 1;
154 if (dist[u] < n)
155 num[dist[u]]++;
156 if (u != s) // »ØÍ˲œ
157 u = pred[u];
158 }
159 }
160 return ret;
161 }
162
163 Network net;
164
165 int maze[maxN][maxN];
166 bool must[maxN][maxN];
167
168 int main() {
169 int nr;
170 int nc;
171 int nk;
172 int sum;
173
174 while (scanf("%d %d %d", &nr, &nc, &nk) != EOF) {
175 sum = 0;
176 memset(must, false, sizeof(must));
177 for (int i = 0; i < nr; i++) {
178 for (int j = 0; j < nc; j++) {
179 scanf("%d", &maze[i][j]);
180 sum += maze[i][j];
181 }
182 }
183 for (int i = 0; i < nk; i++) {
184 int x, y;
185 scanf("%d %d", &x, &y);
186 must[x - 1][y - 1] = true;
187 }
188
189 net.Init(nr * nc + 2, 0, nr * nc + 1);
190 for (int i = 0; i < nr; i++) {
191 for (int j = 0; j < nc; j++) {
192 if ((i + j) & 1) {
193 net.addEdge(0, i * nc + j + 1, must[i][j] ? INF : maze[i][j]);
194 for (int k = 0; k < 4; k++) {
195 int ni = i + dx[k];
196 int nj = j + dy[k];
197 if (ni >= 0 && ni < nr && nj >= 0 && nj < nc) {
198 net.addEdge(i * nc + j + 1, ni * nc + nj + 1, 2
199 * (maze[i][j] & maze[ni][nj]));
200 }
201 }
202 } else {
203 net.addEdge(i * nc + j + 1, nr * nc + 1, must[i][j] ? INF : maze[i][j]);
204 }
205 }
206 }
207
208 int maxFlow = net.maxFlow();
209 printf("%d\n", sum - maxFlow);
210 }
211 return 0;
212 }