zoukankan      html  css  js  c++  java
  • 【BZOJ2756】奇怪的游戏(SCOI2012)-分类讨论+二分+最大流

    测试地址:奇怪的游戏
    做法:本题需要用到分类讨论+二分+最大流。
    首先看到棋盘,先黑白染色,然后我们发现每次操作两个相邻的格子一定是不同色的,意味着黑白格子得到增加的权值和是一样的。那么令x为最后得到的数字,num0/1,sum0/1为黑/白色格子的数量和权值和,有:
    num0xsum0=num1xsum1
    解得:x=sum0sum1num0num1
    num0num1的时候,我们直接解出x,那么现在我们就要判定存不存在解了。实际上,现在就是把每个点的操作次数(即xaij)分配给和它相邻的边,为了方便我们把黑色格子作为分配的点,并且使得分配完之后所有白色格子也得到正好xaij的次数。我们发现这就是一个流量平衡的关系,因此我们从源点向每个黑色格子,从每个白色格子向汇点连一条容量为xaij的边,从每个黑色格子向与它相邻的白色格子连一条容量无限大的边,那么问题有解当且仅当这个网络的最大流等于num0xsum0
    那么当num0=num1时,我们知道nm为偶数,那么若sum0sum1显然无解,否则我们知道,若对于一个x它是有解的,那么对于x+1它也是有解的,因为我们显然可以找到一种方式,使得操作完后所有格子的权值都正好加1(相当于用骨牌覆盖整个棋盘)。因此我们二分x,用上述的方法判定即可。
    以下是本人代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll inf=(1ll<<50);
    int Test,n,m,S,T,first[2010],tot;
    int h,t,q[2010],lvl[2010],cur[2010];
    ll a[45][45],sum[2],num[2];
    struct edge
    {
        int v,next;
        ll f;
    }e[50010];
    
    void insert(int a,int b,ll f)
    {
        e[++tot].v=b,e[tot].next=first[a],e[tot].f=f,first[a]=tot;
        e[++tot].v=a,e[tot].next=first[b],e[tot].f=0,first[b]=tot;
    }
    
    bool makelevel()
    {
        for(int i=1;i<=T;i++)
            lvl[i]=-1,cur[i]=first[i];
        h=t=1;
        q[1]=S;
        lvl[S]=0;
        while(h<=t)
        {
            int v=q[h++];
            for(int i=first[v];i;i=e[i].next)
                if (e[i].f&&lvl[e[i].v]==-1)
                {
                    lvl[e[i].v]=lvl[v]+1;
                    q[++t]=e[i].v;
                }
        }
        return lvl[T]!=-1;
    }
    
    ll maxflow(int v,ll maxf)
    {
        ll ret=0,f;
        if (v==T) return maxf;
        for(int i=cur[v];i;i=e[i].next)
        {
            if (e[i].f&&lvl[e[i].v]==lvl[v]+1)
            {
                f=maxflow(e[i].v,min(maxf-ret,e[i].f));
                ret+=f;
                e[i].f-=f;
                e[i^1].f+=f;
                if (ret==maxf) break;
            }
            cur[v]=i;
        }
        if (!ret) lvl[v]=-1;
        return ret;
    }
    
    bool check(ll x)
    {
        memset(first,0,sizeof(first));
        tot=1;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                if ((i+j)%2)
                {
                    insert(S,(i-1)*m+j,x-a[i][j]);
                    if (i>1) insert((i-1)*m+j,(i-2)*m+j,inf);
                    if (i<n) insert((i-1)*m+j,i*m+j,inf);
                    if (j>1) insert((i-1)*m+j,(i-1)*m+j-1,inf);
                    if (j<m) insert((i-1)*m+j,(i-1)*m+j+1,inf);
                }
                else insert((i-1)*m+j,T,x-a[i][j]);
            }
        ll maxf=0;
        while(makelevel())
            maxf+=maxflow(S,inf);
        if (maxf!=num[0]*x-sum[0]) return 0;
        else return 1;
    }
    
    int main()
    {
        scanf("%d",&Test);
        while(Test--)
        {
            ll maxa=0;
    
            scanf("%d%d",&n,&m);
            S=n*m+1,T=n*m+2;
            sum[0]=sum[1]=num[0]=num[1]=0;
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++)
                {
                    scanf("%lld",&a[i][j]);
                    maxa=max(maxa,a[i][j]);
                    sum[(i+j)%2]+=a[i][j],num[(i+j)%2]++;
                }
    
            if (num[0]!=num[1])
            {
                ll x=(sum[0]-sum[1])/(num[0]-num[1]);
                if (check(x)) printf("%lld
    ",num[0]*x-sum[0]);
                else printf("-1
    ");
            }
            else
            {
                if (sum[0]!=sum[1]) {printf("-1
    ");continue;}
                ll l=maxa,r=inf;
                while(r>l)
                {
                    ll mid=(l+r)>>1;
                    if (check(mid)) r=mid;
                    else l=mid+1;
                }
                printf("%lld
    ",num[0]*l-sum[0]);
            }
        }
    
        return 0;
    }
  • 相关阅读:
    高精度加法_蓝桥杯
    高精度阶乘计算_蓝桥杯
    闰年判断_蓝桥杯
    01字串_蓝桥杯
    字母图形_蓝桥杯
    禅道本地环境搭建(新猿旺学习总结)
    kvm管理
    kvm批量创建虚拟机
    7.正则RE
    ansible-playbook
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793434.html
Copyright © 2011-2022 走看看