样例全过,讨论区 datamaker 数据全过。debug 一个晚上了,请问是哪里写挂了?
#include <bits/stdc++.h>
using namespace std;
#define inf 1000000000000000
#define V 100100
#define E 500100
typedef long long int ll;
struct edge {
int to, next;
ll capa, cost;
};
int cnt = 0, head[V], n, m; edge node[E];
inline void add(int fir, int nxt, ll w, ll c) {
node[cnt].to = nxt,
node[cnt].capa = w,
node[cnt].cost = c,
node[cnt].next = head[fir],
head[fir] = cnt++;
}
int s, t, cur[V]; deque<int>que; ll dep[V], sum = 0, cost = 0, rsum = 0;
bool vis[V];
inline bool spfa() {
for (register int i = 1; i <= t; ++i)dep[i] = inf;
dep[s] = 0; que.push_back(s); int u, v;
while (!que.empty()) {
v = que.front(); que.pop_front();
for (register int i = head[v]; i != -1; i = node[i].next) {
u = node[i].to;
if (dep[v] + node[i].cost < dep[u] && node[i].capa) {
dep[u] = dep[v] + node[i].cost;
if (!que.empty() && dep[u] < dep[que.front()])que.push_front(u);
else que.push_back(u);
}
}
}
return (dep[t] != inf);
}
ll dfs(register int v, register ll flow) {
if (v == t || flow == 0)return flow; ll used = 0, wei = 0;
vis[v] = true;
for (register int i = cur[v]; i != -1; i = node[i].next) {
cur[v] = i;
if (!vis[node[i].to] && dep[node[i].to] == dep[v] + node[i].cost && node[i].capa) {
wei = dfs(node[i].to, min(flow - used, node[i].capa));
if (wei) {
node[i].capa -= wei,
node[i ^ 1].capa += wei,
used += wei,
cost += node[i].cost * wei;
}
}
if (used == flow)break;
}
vis[v] = false;
return used;
}
inline void Dinic() {
while (spfa()) {
memcpy(cur, head, (t + 1) * sizeof(int));
sum += dfs(s, inf);
}
}
inline void addE(int u, int v, ll w, ll c, bool col = true) {
if (!col)swap(u, v);
add(u, v, w, c);
add(v, u, 0, -c);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(); cout.tie();
memset(head, -1, V * sizeof(int));
cin >> n >> m; s = n * m * 5 + 1, t = n * m * 5 + 2;
int f, l, v, dir = n * m; ll w, c; bool col;//黑为 true,白为 false
//dir = n*m,dir*1 上,dir*2 右,dir*3 下,dir*4 左
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cin >> w; v = (i - 1) * m + j;
if (col = !(i + j & 1))addE(s, v, inf, 0, 1);
else addE(v, t, inf, 0, 1);
if (w & 1)addE(v, v + dir, 1, 0, col),++rsum;
if (w & 2)addE(v, v + dir * 2, 1, 0, col),++rsum;
if (w & 4)addE(v, v + dir * 3, 1, 0, col),++rsum;
if (w & 8)addE(v, v + dir * 4, 1, 0, col),++rsum;
if (col) {
if (i - 1)addE(v + dir, v - m + dir * 3, 1, 0, col);//上
if (j - 1)addE(v + dir * 4, v - 1 + dir * 2, 1, 0, col);//左
if (i + 1 <= n)addE(v + dir * 3, v + m + dir, 1, 0, col);//下
if (j + 1 <= m)addE(v + dir * 2, v + 1 + dir * 4, 1, 0, col);//右
}
switch (w) {
case 0:break;
case 1: {//0001,上有接头
addE(v + dir, v + dir * 4, 1, 1, col);
addE(v + dir, v + dir * 2, 1, 1, col);
addE(v + dir, v + dir * 3, 1, 2, col);
break;
}
case 2: {//0010,右有接头
addE(v + dir * 2, v + dir, 1, 1, col);
addE(v + dir * 2, v + dir * 4, 1, 2, col);
addE(v + dir * 2, v + dir * 3, 1, 1, col);
break;
}
case 3: {//0011,上右有接头
addE(v + dir, v + dir * 3, 1, 1, col);//上连下
addE(v + dir * 2, v + dir * 4, 1, 1, col);//右连左
break;
}
case 4: {//0100,下有接头
addE(v + dir * 3, v + dir * 2, 1, 1, col);
addE(v + dir * 3, v + dir * 4, 1, 1, col);
addE(v + dir * 3, v + dir, 1, 2, col);
break;
}
case 5: {//0101,上下有接头
if (i - 1)addE(v + dir, v - m + dir * 3, 1, 0, col);
if (i + 1 <= n)addE(v + dir * 4, v + m + dir, 1, 0, col);
break;
}
case 6: {//0110,下右有接头
addE(v + dir * 3, v + dir, 1, 1, col);//下连上
addE(v + dir * 2, v + dir * 4, 1, 1, col);//右连左
break;
}
case 7: {//0111,上下右有接头
addE(v + dir, v + dir * 4, 1, 1, col);
addE(v + dir * 2, v + dir * 4, 1, 2, col);
addE(v + dir * 3, v + dir * 4, 1, 1, col);
break;
}
case 8: {//1000,左有接头
addE(v + dir * 4, v + dir, 1, 1, col);
addE(v + dir * 4, v + dir * 2, 1, 2, col);
addE(v + dir * 4, v + dir * 3, 1, 1, col);
break;
}
case 9: {//1001,上左有接头
addE(v + dir * 4, v + dir * 2, 1, 1, col);
addE(v + dir, v + dir * 3, 1, 1, col);
break;
}
case 10: {//1010,左右有接头
if (j - 1)addE(v + dir * 2, v - 1 + dir * 4, 1, 0, col);
if (j + 1 <= m)addE(v + dir * 4, v + 1 + dir * 2, 1, 0, col);
break;
}
case 11: {//1011,左右上有接头
addE(v + dir * 4, v + dir * 3, 1, 1, col);
addE(v + dir, v + dir * 3, 1, 2, col);
addE(v + dir * 2, v + dir * 3, 1, 1, col);
break;
}
case 12: {//1100,下左有接头
addE(v + dir * 3, v + dir, 1, 1, col);
addE(v + dir * 4, v + dir * 2, 1, 1, col);
break;
}
case 13: {//1101,上下左有接头
addE(v + dir * 4, v + dir * 2, 1, 2, col);
addE(v + dir, v + dir * 2, 1, 1, col);
addE(v + dir * 3, v + dir * 2, 1, 1, col);
break;
}
case 14: {//1110,下左右有接头
addE(v + dir * 4, v + dir, 1, 1, col);
addE(v + dir * 3, v + dir, 1, 2, col);
addE(v + dir * 2, v + dir, 1, 1, col);
break;
}
case 15: break;
}
}
}
Dinic();
if (sum * 2 != rsum)cout << "-1";
else cout << cost;
return 0;
}