bzoj 2756

2756

 

思路:

  二分讨论,网络流检验;

 

代码:

#include <bits/stdc++.h>
using namespace std;
#define INF 1e16
#define maxn 40005
#define ll long long
const ll dx[5]={0,-1,0,1,0};
const ll dy[5]={0,0,1,0,-1};
ll ai[45][45],id[45][45],suma,sumb,cnta,cntb,que[maxn],Max,ans;
ll deep[maxn],E[maxn],V[maxn],F[maxn],cnt,head[maxn],s,t,cntid;
ll n,m;
bool col[45][45];
inline void in(ll &now)
{
    char Cget=getchar();now=0;
    while(Cget>'9'||Cget<'0') Cget=getchar();
    while(Cget>='0'&&Cget<='9')
    {
        now=now*10+Cget-'0';
        Cget=getchar();
    }
}
inline void edge_add(ll u,ll v,ll f)
{
    E[++cnt]=head[u],V[cnt]=v,F[cnt]=f,head[u]=cnt;
    E[++cnt]=head[v],V[cnt]=u,F[cnt]=0,head[v]=cnt;
}
bool bfs()
{
    for(ll i=s;i<=t;i++) deep[i]=-1;
    deep[s]=0,que[0]=s;ll h=0,tail=1,now;
    while(h<tail)
    {
        now=que[h++];
        for(ll i=head[now];i;i=E[i])
            if(F[i]&&deep[V[i]]==-1)
            {
                deep[V[i]]=deep[now]+1;
                if(V[i]==t) return true;
                que[tail++]=V[i];
            }
    }
    return false;
}
ll flowing(ll now,ll flow)
{
    if(now==t||flow<=0) return flow;
    ll oldflow=0,pos;
    for(ll i=head[now];i;i=E[i])
    {
        if(!F[i]||deep[V[i]]!=deep[now]+1) continue;
        pos=flowing(V[i],min(flow,F[i]));
        F[i]-=pos,F[i^1]+=pos,oldflow+=pos,flow-=pos;
        if(!flow) return oldflow;
    }
    if(!oldflow) deep[now]=-1;
    return oldflow;
}
bool check(ll x)
{
    for(ll i=s;i<=t;i++) head[i]=0;cnt=1;
    for(ll i=1;i<=n;i++)
        for(ll v=1;v<=m;v++)
            if(col[i][v])
            {
                edge_add(s,id[i][v],x-ai[i][v]);
                for(ll e=1;e<=4;e++)
                    if(i+dx[e]>0&&i+dx[e]<=n&&v+dy[e]>0&&v+dy[e]<=m) edge_add(id[i][v],id[i+dx[e]][v+dy[e]],INF);
            }
            else edge_add(id[i][v],t,x-ai[i][v]);
    ll res=0;
    while(bfs()) res+=flowing(s,INF);
    return res==(x*cnta-suma);
}
int main()
{
    freopen("data.txt","r",stdin);
    ll T;in(T);
    while(T--)
    {
        in(n),in(m),suma=0,sumb=0,cnta=0,cntb=0,cntid=0,Max=0;
        for(ll i=1;i<=n;i++)
            for(ll v=1;v<=m;v++)
            {
                in(ai[i][v]),col[i][v]=(i+v)%2;
                if(col[i][v]) suma+=ai[i][v],cnta++;
                else sumb+=ai[i][v],cntb++;
                id[i][v]=++cntid,Max=max(Max,ai[i][v]);
            }
        ans=-1,s=0,t=cntid+1;
        if(cnta!=cntb)
        {
            if((suma-sumb)%(cnta-cntb)==0)
            {
                ll x=(suma-sumb)/(cnta-cntb);
                if(x>=Max) if(check(x)) ans=x*cnta-suma;
            }
        }
        else
        {
            if(suma==sumb)
            {
                ll l=Max,r=INF,mid;
                while(l<=r)
                {
                    mid=l+r>>1;
                    if(check(mid)) r=mid-1,ans=mid;
                    else l=mid+1;
                }
                if(ans!=-1) ans=ans*cnta-suma;
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

posted @ 2017-08-09 17:49  IIIIIIIIIU  阅读(263)  评论(0编辑  收藏  举报