BZOJ 2756 奇怪的游戏

1.二分+网络流+各种判。

2.网上很多程序都是错的。

3.一个%lld打成%d调了一年。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define maxn 45
#define maxv 1700
#define maxe 1000500
#define inf (1LL<<50)
using namespace std;
long long tt,n,m,map[maxn][maxn],col[maxn][maxn],n1=0,n2=0,s1=0,s2=0,mx=0;
long long dx[]={0,0,1,0,-1},dy[]={0,1,0,-1,0};
long long dis[maxv],nume=1,g[maxv],s,t;
queue <long long> q;
bool vis[maxv];
struct edge
{
    long long v,f,nxt;
}e[maxe];
long long p(long long x,long long y)
{
    return (x-1)*m+y;
}
void addedge(long long u,long long v,long long f)
{
    e[++nume].v=v;e[nume].f=f;e[nume].nxt=g[u];g[u]=nume;
    e[++nume].v=u;e[nume].f=0;e[nume].nxt=g[v];g[v]=nume;
}
bool checks(long long x,long long y)
{
    if ((x>=1) && (x<=n) && (y>=1) && (y<=m)) return true;
    return false;
}
void build(long long x)
{
    nume=1;memset(g,0,sizeof(g));
    s=0;t=n1+n2+1;
    for (long long i=1;i<=n;i++)
        for (long long j=1;j<=m;j++)
        {
            long long now=p(i,j);
            if (col[i][j]) addedge(s,now,x-map[i][j]);
            else addedge(now,t,x-map[i][j]);
            if (col[i][j])
            {
                for (long long k=1;k<=4;k++)
                {
                    long long a=i+dx[k],b=j+dy[k],ret=p(a,b);
                    if (checks(a,b)) addedge(now,ret,inf);
                }
            }
        }
}
bool bfs()
{
    for (long long i=s;i<=t;i++) {dis[i]=inf;vis[i]=false;}
    q.push(s);dis[s]=0;vis[s]=true;
    while (!q.empty())
    {
        long long head=q.front();q.pop();
        for (long long i=g[head];i;i=e[i].nxt)
        {
            long long v=e[i].v;
            if ((e[i].f) && (dis[v]>dis[head]+1))
            {
                dis[v]=dis[head]+1;
                if (!vis[v]) {q.push(v);vis[v]=true;}
            }
        }
    }
    if (dis[t]==inf) return false;
    return true;
}
long long dinic(long long x,long long low)
{
    if (x==t) return low;
    long long ret=0;
    for (long long i=g[x];i && low;i=e[i].nxt)
    {
        long long v=e[i].v;
        if ((e[i].f) && (dis[v]==dis[x]+1))
        {
            long long dd=dinic(v,min(e[i].f,low));
            e[i].f-=dd;e[i^1].f+=dd;
            ret+=dd;low-=dd;
        }
    }
    if (!ret) dis[x]=inf;
    return ret;
}
bool check(long long x)
{
    build(x);
    long long max_flow=0,ret=0;
    while (bfs())
        max_flow+=dinic(s,inf);
    for (long long i=1;i<=n;i++)
        for (long long j=1;j<=m;j++)
            if (col[i][j]) ret+=(x-map[i][j]);
    if (ret==max_flow) return true;
    return false;
}
void work1()
{
    long long x=(s1-s2)/(n1-n2);
    if (x>=mx)
        if (check(x))
        {
            long long ret=x*(n1+n2)-s1-s2;
            printf("%lld\n",(x*(n1+n2)-s1-s2)/2);
            return;
        }
    printf("-1\n");
}
void work2()
{
    if (s1!=s2) {printf("-1\n");return;}
    long long l=mx,r=inf,ans=inf;
    while (l<=r)
    {
        long long mid=l+r>>1;
        if (check(mid)) {ans=mid;r=mid-1;}
        else l=mid+1;
    }
    if (ans==inf) printf("-1\n");
    else printf("%lld\n",(ans*(n1+n2)-s1-s2)/2);
    return;
}
void work()
{
    n1=0;n2=0;s1=0;s2=0;mx=0;
    scanf("%lld%lld",&n,&m);
    for (long long i=1;i<=n;i++)
        for (long long j=1;j<=m;j++)
        {
            scanf("%lld",&map[i][j]);
            mx=max(mx,map[i][j]);
        }
    if ((n==1) && (m==1))
    {
        printf("0\n");
        return;
    }
    col[1][1]=1;
    for (long long i=1;i<=n;i++)
        for (long long j=1;j<=m;j++)
            for (long long k=1;k<=4;k++)
                col[i+dx[k]][j+dy[k]]=col[i][j]^1;
    for (long long i=1;i<=n;i++)
        for (long long j=1;j<=m;j++)
        {
            if (col[i][j]) {n1++;s1+=map[i][j];}
            else {n2++;s2+=map[i][j];}
        }
    if (n1!=n2) work1();
    else work2();
}
int main()
{
    scanf("%lld",&tt);
    for (long long i=1;i<=tt;i++)
        work();
    return 0;
}
时间: 2024-11-05 13:29:43

BZOJ 2756 奇怪的游戏的相关文章

BZOJ 2756 奇怪的游戏(最大流)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2756 题意:在一个 N*M 的棋盘上玩,每个格子有一个数.每次 选择两个相邻的格子,并使这两个数都加上 1. 问最少多少次能使棋盘上的数都变成同一个数,如果永远不能变成同一个数则输出-1. 思路:对棋盘进行黑白染色,则每次操作使得黑白两色的格子总和各增加1.设黑色总和s1,个数cnt1:白色总和s2,个数cnt2,设最后的数字为x,那么有: x*cnt1-s1=x*cnt2-s2. (

bzoj 2756奇怪的游戏

2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 2571  Solved: 685[Submit][Status][Discuss] Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻的格子,并使这两个数都加上 1. 现在 Blinker 想知道最少多少次能使棋盘上的数都变成同一个数,如果永远不能变成

BZOJ 2756: [SCOI2012]奇怪的游戏 [最大流 二分]

2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 3352  Solved: 919[Submit][Status][Discuss] Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻的格子,并使这两个数都加上 1. 现在 Blinker 想知道最少多少次能使棋盘上的数都变成同一个数,如果永远不能变成

BZOJ 2756: [SCOI2012]奇怪的游戏 网络流/二分

2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 1594  Solved: 396[Submit][Status][Discuss] Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻 的格子,并使这两个数都加上 1. 现在 Blinker 想知道最少多少次能使棋盘上的数都变成同一个数,如果永远不能变

BZOJ 2756: [SCOI2012]奇怪的游戏

2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 3410  Solved: 941[Submit][Status][Discuss] Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻的格子,并使这两个数都加上 1. 现在 Blinker 想知道最少多少次能使棋盘上的数都变成同一个数,如果永远不能变成

BZOJ 2756 SCOI2012 奇怪的游戏 最大流

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2756 Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻的格子,并使这两个数都加上 1. 现在 Blinker 想知道最少多少次能使棋盘上的数都变成同一个数,如果永远不能变成同一个数则输出-1. Input 输入的第一行是一个整数T,表示输入数据有T轮游戏组成. 每轮游戏的第一行有两

BZOJ 2756 SCOI 奇怪的游戏

2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 4978  Solved: 1381[Submit][Status][Discuss] Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻的格子,并使这两个数都加上 1. 现在 Blinker 想知道最少多少次能使棋盘上的数都变成同一个数,如果永远不能变

【BZOJ】【2756】【SCOI2012】奇怪的游戏

网络流-最大流 这题……建模部分先略过 这道题是会卡时限的T_T俺的Dinic被卡了,在此放几篇很棒的讲网络流算法的文章,至于大家耳熟能详的论文就不放了…… http://www.cppblog.com/panzhizhou/articles/172978.html?opt=admin 里面的各种超链接也很不错的……       好的来重新更新一下……这题因为要二分,需要多次重建跑最大流,所以不能用像lrj大爷的白书上那样用vector存边(太慢),需用前向星= = 然后……本蒻由于第一次写前向

【BZOJ-2756】奇怪的游戏 最大流 + 分类讨论

2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 2925  Solved: 792[Submit][Status][Discuss] Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻的格子,并使这两个数都加上 1. 现在 Blinker 想知道最少多少次能使棋盘上的数都变成同一个数,如果永远不能变成