#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10,M = 2e4+10,inf = 0x3f3f3f3f;
int n,m,s,t,op;
struct edge{
int u,v,w,c,nxt;
}e[2*M];
int tot = -1,h[N];
int maxflow,mincost;
int flow[M];
int jo;
inline void add(int u,int v,int w,int c){
if(!jo)swap(u,v);
e[++tot].u = u;
e[tot].v = v;
e[tot].w = w;
e[tot].c = c;
e[tot].nxt = h[u];
h[u] = tot;
e[++tot].u = v;
e[tot].v = u;
e[tot].w = 0;
e[tot].c = -c;
e[tot].nxt = h[v];
h[v] = tot;
}
int d[N],vis[N],pre[N],realflow,ff[4] = {2,3,0,1};
int dx[4] = {0,1,0,-1};
int dy[4] = {1,0,-1,0};
inline int spfa(){
memset(flow,0x7f,sizeof flow);
memset(d,0x7f,sizeof d);
memset(vis,0,sizeof vis);
queue<int>q;
d[s] = 0;
vis[s] = 1;
q.push(s);
flow[s] = inf;
pre[t] = -1;
while(!q.empty()){
int u = q.front();q.pop();
vis[u] = 0;
for(int i = h[u];i >= 0;i = e[i].nxt){
// cout << e[i].c <<endl;
if(!e[i].w)continue;
int v = e[i].v;
if(d[v] > d[u] + e[i].c){
d[v] = d[u] + e[i].c;
flow[v] = min(flow[u],e[i].w);
pre[v] = i;
if(!vis[v]){
q.push(v);
vis[v] = 1;
}
}
}
}
return ~pre[t];
}
void MCMF(){
while(spfa()){
int x = t;
mincost += d[t] * flow[t];
maxflow += flow[t];
int now;
while(x != s){
now = pre[x];
e[now].w -= flow[t];
e[now^1].w += flow[t];
x = e[now^1].v;
}
}
}
inline int f(int i,int j,int w){return (i-1)*m+j+w*n*m;}
int main(){
cin.tie(0);
cout.tie(0);
cin >> n >> m;
s = 5*n*m+1;
t = 5*n*m+2;
memset(h,-1,sizeof h);
for(int i = 1;i <= n;i ++){
jo = i & 1;
for(int j = 1;j <= m;j ++){
cin >> op;
jo ^= 1;
if(jo){
add(s,f(i,j,4),inf,0);
for(int k = 0;k < 4;k ++){
int x = i + dx[k],y = j + dy[k];
if(x < 1 || x > n || y < 1 || y > m)continue;
add(f(i,j,k),f(x,y,ff[k]),1,0);
}
for(int k = 0;k < 4;k ++){
if(op & (1 << k)){
add(f(i,j,4),f(i,j,k),1,0);
++ realflow;
}
}
}else{
add(t,f(i,j,4),inf,0);
for(int k = 0;k < 4;k ++){
if(op & (1 << k)){
add(f(i,j,4),f(i,j,k),1,0);
++ realflow;
}
}
}
if(op == 8){
add(f(i,j,3),f(i,j,0),1,1);
add(f(i,j,3),f(i,j,2),1,1);
add(f(i,j,3),f(i,j,1),1,2);
continue;
}
if(op == 4){
add(f(i,j,2),f(i,j,1),1,1);
add(f(i,j,2),f(i,j,3),1,1);
add(f(i,j,2),f(i,j,0),1,2);
continue;
}
if(op == 2){
add(f(i,j,1),f(i,j,0),1,1);
add(f(i,j,1),f(i,j,2),1,1);
add(f(i,j,1),f(i,j,3),1,2);
continue;
}
if(op == 1){
add(f(i,j,0),f(i,j,1),1,1);
add(f(i,j,0),f(i,j,3),1,1);
add(f(i,j,0),f(i,j,2),1,2);
continue;
}
if(op == 3){
add(f(i,j,1),f(i,j,3),1,1);
add(f(i,j,0),f(i,j,2),1,1);
continue;
}
if(op == 6){
add(f(i,j,1),f(i,j,3),1,1);
add(f(i,j,2),f(i,j,0),1,1);
continue;
}
if(op == 9){
add(f(i,j,3),f(i,j,1),1,1);
add(f(i,j,0),f(i,j,2),1,1);
continue;
}
if(op == 12){
add(f(i,j,3),f(i,j,1),1,1);
add(f(i,j,2),f(i,j,0),1,1);
continue;
}
if(op == 7){
add(f(i,j,0),f(i,j,3),1,1);
add(f(i,j,2),f(i,j,3),1,1);
add(f(i,j,1),f(i,j,3),1,2);
continue;
}
if(op == 11){
add(f(i,j,3),f(i,j,2),1,1);
add(f(i,j,1),f(i,j,2),1,1);
add(f(i,j,0),f(i,j,2),1,2);
continue;
}
if(op == 13){
add(f(i,j,0),f(i,j,1),1,1);
add(f(i,j,2),f(i,j,1),1,1);
add(f(i,j,3),f(i,j,1),1,2);
continue;
}
if(op == 14){
add(f(i,j,3),f(i,j,0),1,1);
add(f(i,j,1),f(i,j,0),1,1);
add(f(i,j,2),f(i,j,0),1,2);
continue;
}
}
}
MCMF();
// for(int i = 1;i <= tot;i ++)cout << e[i].c << endl;
// cout << maxflow <<' ' << mincost << endl;
if(maxflow*2==realflow)cout << mincost << endl;
else cout << -1 << endl;
return 0;
}
最常规的MCMF做法。
最大流求的没啥问题,但最小花费不对。
因为太弱了调不出来所以求助。谢谢