首先这个题有一些情况不满足二分的性质,即黑白块数不相等的情况,这种情况满足的最后数字是可以直接求出来的
因为有解的条件 x*cnt1-ans1==x*cnt0-ans0,x是唯一解
相等的情况 上式就等价于x=x。。
所以另外一个解的判定方法就是按照当前x能不能及时分配完,由于点与点之间的关系连成一片,要用网络流
注意eps的大小!!
码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define inf 1125899906842624
#define ll long long
queue<int>q;
ll ans1,ans0,cnt1,cnt0,l,r,mid;
ll xia[2000],yuan[2000],tot,zhong[100000],v[1000000],hou[100000],T,n,m,i,j,s,t,d[55][55],dd[2000];
void jian(ll a,ll b,ll C)
{
++tot,hou[tot]=yuan[a],yuan[a]=tot,zhong[tot]=b,v[tot]=C;
}
void jia(ll a,ll b,ll C)
{
jian(a,b,C);
jian(b,a,0);
}
bool bfs()
{
int i;
for(i=1;i<=t;i++)xia[i]=yuan[i],dd[i]=inf;
dd[s]=0;
q.push(s);
while(!q.empty())
{
int st=q.front();
q.pop();
for(i=xia[st];i!=-1;i=hou[i])
{
int nd=zhong[i];
if(v[i]>0&&dd[nd]==inf)dd[nd]=dd[st]+1,q.push(nd);
}
}
return dd[t]!=inf;
}
ll dfs(int o,ll limit)
{
if(!limit||o==t)return limit;
ll f=0,flow=0,i;
for(i=xia[o];i!=-1;i=hou[i])
{
xia[o]=i;
int nd=zhong[i];
if(dd[nd]==dd[o]+1&&(f=dfs(nd,min(limit,v[i]))))
{
flow+=f;
limit-=f;
v[i]-=f;
v[i^1]+=f;
if(!limit)break;
}
}
return flow;
}
ll dinic()
{
ll ans=0;
while(bfs())
ans+=dfs(s,inf);
return ans;
}
ll work(ll mid)
{
tot=-1; memset(yuan,-1,sizeof(xia));
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
if((i+j)&1)
{
jia(s,(i-1)*m+j,mid-d[i][j]);
if(i>1)jia((i-1)*m+j,(i-2)*m+j,inf);
if(j>1)jia((i-1)*m+j,(i-1)*m+j-1,inf);
if(i<n)jia((i-1)*m+j,(i)*m+j,inf);
if(j<m)jia((i-1)*m+j,(i-1)*m+j+1,inf);
}else
{
jia((i-1)*m+j,t,mid-d[i][j]);
}
}
return dinic();
}
int main()
{
scanf("%lld",&T);
while(T--)
{
scanf("%lld%lld",&n,&m);
s=n*m+1;t=n*m+2;
ans1=ans0=cnt1=cnt0=0;l=0;r=inf;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
scanf("%lld",&d[i][j]);
if((i+j)&1)ans1+=d[i][j],cnt1++;
else ans0+=d[i][j],cnt0++;
l=max(l,d[i][j]);
}
if((n&1)&&(m&1))
{
if((ans1-ans0)/(cnt1-cnt0)>=l&&work((ans1-ans0)/(cnt1-cnt0))==((ans1-ans0)/(cnt1-cnt0))*cnt1-ans1)printf("%lld\n",(ans1-ans0)/(cnt1-cnt0)*cnt1-ans1);
else printf("-1\n");
}else
{
if(ans0!=ans1)
{
printf("-1\n");
continue;
}
while(l<r)
{
mid=(l+r)>>1;
if(work(mid)==(mid*cnt1-ans1))
{
r=mid;
}else l=mid+1;
}
printf("%lld\n",l*cnt1-ans1);
}
}
}