BZOJ 2756 奇怪的游戏
Posted ziliuziliu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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; }
以上是关于BZOJ 2756 奇怪的游戏的主要内容,如果未能解决你的问题,请参考以下文章