把图上的每个点拆成两个点,按照老套路连边,把交换的连边流量无穷、代价为1,其余的边流量为1、代价为0,如果满流就输出代价
注意num1和num2数组的值,这里的id不能重复!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define inf 0x3F3F3F3F
using namespace std;
struct Node
{
int to,next,v,cost;
}e[100005];
int S,T,P,a[25][25],b[25][25],num1[25][25],num2[25][25],cnt=1;
int h[10005],d[10005],pre[10005],flow,cost;
bool vis[10005];
inline void Addedge(int x,int y,int v,int cost=0)
{
e[++cnt]=(Node){y,h[x],v,cost};h[x]=cnt;
e[++cnt]=(Node){x,h[y],0,-cost};h[y]=cnt;
return;
}
inline bool SPFA()
{
int i,x,y;
queue<int>q;q.push(S);
memset(d,0x3F,sizeof(d));d[S]=0;
memset(vis,0,sizeof(vis));
memset(pre,0,sizeof(pre));
while(!q.empty())
{
x=q.front();q.pop();
vis[x]=false;
for(i=h[x];i;i=e[i].next)
{
y=e[i].to;
if(e[i].v&&d[y]>d[x]+e[i].cost)
{
d[y]=d[x]+e[i].cost;
pre[y]=i;
if(!vis[y]){vis[y]=true;q.push(y);}
}
}
}
if(d[T]<0x3F3F3F3F)return true;
return false;
}
inline void Adjust()
{
int i,j=T,delta=0x3F3F3F3F;
while(pre[j])
{
i=pre[j];
if(e[i].v<delta)delta=e[i].v;
j=e[i^1].to;
}
cost+=delta*d[T];
flow+=delta;
j=T;
while(pre[j])
{
i=pre[j];
e[i].v-=delta;
e[i^1].v+=delta;
j=e[i^1].to;
}
return;
}
const int dx[]={-1,-1,-1,0,0,1,1,1},dy[]={-1,0,1,-1,1,-1,0,1};
int main(void)
{
int i,j,k,x,newx,newy,n,m,ch,sum=0,id=0;
scanf("%d%d",&n,&m);
for(i=1;i<=n;++i)
{
for(j=1;j<=m;++j)
{
while(ch=getchar())if(ch>='0'&&ch<='9')break;
a[i][j]=ch-'0';sum+=a[i][j];
}
}
for(i=1;i<=n;++i)
{
for(j=1;j<=m;++j)
{
while(ch=getchar())if(ch>='0'&&ch<='9')break;
b[i][j]=ch-'0';sum-=b[i][j];
}
}
if(sum){printf("-1\n");return 0;}
for(i=1;i<=n;++i)
{
for(j=1;j<=m;++j)num1[i][j]=++id;
}
for(i=1;i<=n;++i)
{
for(j=1;j<=m;++j)num2[i][j]=++id;
}
S=2*n*m+1;T=P=2*n*m+2;
for(i=1;i<=n;++i)
{
for(j=1;j<=m;++j)
{
if(a[i][j]&&!b[i][j])Addedge(S,num1[i][j],1),++sum;
if(!a[i][j]&&b[i][j])Addedge(num2[i][j],T,1);
}
}
for(i=1;i<=n;++i)
{
for(j=1;j<=m;++j)
{
while(ch=getchar())if(ch>='0'&&ch<='9')break;
x=ch-'0';
Addedge(num1[i][j],num2[i][j],x>>1);
if((a[i][j]!=b[i][j])&&(x&1))Addedge(num1[i][j],num2[i][j],1);
for(k=0;k<8;++k)
{
newx=i+dx[k];newy=j+dy[k];
if(newx<1||newx>n||newy<1||newy>m)continue;
Addedge(num2[i][j],num1[newx][newy],inf,1);
}
}
}
while(SPFA())Adjust();
if(flow!=sum){printf("-1\n");return 0;}
printf("%d\n",cost);
return 0;
}