/*
和1565一样:
总点数的权 - 最小覆盖点集 = 最大独立集
--------------------------------------
void add(int u, int v, int f)加边
{
e[ct].u = u;
e[ct].v = v;
e[ct].f = f;
next[ct] = first[u];
first[u] = ct++;
e[ct].u = v;
e[ct].v = u;
e[ct].f = 0;
next[ct] = first[v];
first[v] = ct++;
}
--------------------------------------
memset(p,-1,sizeof(p);???????
--------------------------------------
for(int i=first[u]; i!=-1; i=next[i])
{
if(!a[e[i].v]&&e[i].f)找新结点e[i].v
{
p[e[i].v]=i;记录e[i].v的父亲
a[e[i].v]=min(a[u],e[i].f);s-e[i].v路径上的最小残量和
q.push(e[i].v);父亲加入队列
}
}
--------------------------------------
for(int u=t; u!=s; u=e[p[u]].u)从汇点往回用走
{
e[p[u]].f-=a[t];
e[p[u]^1].f+=a[t];异或的作用
}
--------------------------------------
建图,题目的关键。。用奇偶建立二分图
代码理解:
for(int i=1; i<=m; i++)
{
for(int j=1; j<=n; j++)
{
int tmp=(i-1)*n+j;格子从1.....n*m编号,tmp是格子的编号
if((i+j)%2==0)偶数
{
add(s,tmp,g[i][j]);与源点相连
if(i>1)
add(tmp,(i-2)*n+j,INF);
if(i<m)
add(tmp,i*n+j,INF);
if(j>1)
add(tmp,(i-1)*n+j-1,INF);
if(j<n)
add(tmp,(i-1)*n+j+1,INF);
}
else
add(tmp,t,g[i][j]);与汇点
}
}
---------------------------------
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
struct node
{
int u,v,f;
} e[60000];
int n,m;
int p[3000];
int first[3000],next[60000],ct;
int g[55][55];
int a[3000];
int sum;
int s,t;
void add(int u, int v, int f)
{
e[ct].u = u;
e[ct].v = v;
e[ct].f = f;
next[ct] = first[u];
first[u] = ct++;
e[ct].u = v;
e[ct].v = u;
e[ct].f = 0;
next[ct] = first[v];
first[v] = ct++;
}
int EK(int s, int t)
{
queue<int> q;
int f=0;
while(1)
{
memset(a,0,sizeof(a));
memset(p,-1,sizeof(p));
q.push(s);
a[s]=INF;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=first[u]; i!=-1; i=next[i])
{
if(!a[e[i].v]&&e[i].f)
{
p[e[i].v]=i;
a[e[i].v]=min(a[u],e[i].f);
q.push(e[i].v);
}
}
}
if(a[t]==0)
break;
for(int u=t; u!=s; u=e[p[u]].u)
{
e[p[u]].f-=a[t];
e[p[u]^1].f+=a[t];
}
f+=a[t];
}
return f;
}
void init()
{
sum = 0;
ct = 0;
memset(first,-1,sizeof(first));
memset(next,-1,sizeof(next));
for(int i=1; i<=m; i++)
{
for(int j=1; j<=n; j++)
{
scanf("%d",&g[i][j]);
sum += g[i][j];
}
}
for(int i=1; i<=m; i++)
{
for(int j=1; j<=n; j++)
{
int tmp=(i-1)*n+j;
if((i+j)%2==0)
{
add(s,tmp,g[i][j]);
if(i>1)
add(tmp,(i-2)*n+j,INF);
if(i<m)
add(tmp,i*n+j,INF);
if(j>1)
add(tmp,(i-1)*n+j-1,INF);
if(j<n)
add(tmp,(i-1)*n+j+1,INF);
}
else
add(tmp,t,g[i][j]);
}
}
}
int main()
{
//freopen("input.txt","r",stdin);
while(scanf("%d%d",&m,&n) != EOF)
{
s=0;
t=n*m+1;
init();
printf("%d\n",sum - EK(s, t));
}
return 0;
}
---------------------------------------------------------------------
。。。。。。。。。。。。。。。。。。。。。。。。