bzoj2756 [SCOI2012] Extraña conclusión del juego + flujo de red

En primer lugar, hay algunas situaciones en esta pregunta que no satisfacen la dicotomía, es decir, el número de bloques en blanco y negro no es igual, el número final satisfecho en este caso se puede calcular directamente.

Debido a que existe una condición de solución x * cnt1-ans1 == x * cnt0-ans0, x es la única solución

En el caso de igualdad, la fórmula anterior es equivalente ax = x. .

Entonces, otra forma de determinar la solución es determinar si la corriente x se puede asignar en el tiempo. Dado que la relación entre los puntos está conectada en una sola pieza, se usa el flujo de red

¡Presta atención al tamaño de los eps! !

código:

#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);   
     }   
    }
}




Supongo que te gusta

Origin blog.csdn.net/haobang866/article/details/79365131
Recomendado
Clasificación