Description
Blinker最近喜欢上一个奇怪的游戏。
这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数。每次 Blinker 会选择两个相邻
的格子,并使这两个数都加上 1。
现在 Blinker 想知道最少多少次能使棋盘上的数都变成同一个数,如果永远不能变成同
一个数则输出-1。
Input
输入的第一行是一个整数T,表示输入数据有T轮游戏组成。
每轮游戏的第一行有两个整数N和M, 分别代表棋盘的行数和列数。
接下来有N行,每行 M个数。
Output
对于每个游戏输出最少能使游戏结束的次数,如果永远不能变成同一个数则输出-1。
Sample Input
2
2 2
1 2
2 3
3 3
1 2 3
2 3 4
4 3 2
2 2
1 2
2 3
3 3
1 2 3
2 3 4
4 3 2
Sample Output
2
-1
-1
现场没有想出正解QAQ
结论+二分网络流
首先对所有格子黑白染色,显然每涂一次只能涂一黑一白
假设所有黑色格子的权值之和为s1,白色格子权值之和为s2,黑色格子有d1个,白色格子有d2个
假设我们要到达所有格子都是x的状态
那么因为每次增加的是一黑一白,很容易列出方程式
d1*x-s1=d2*x-s2
x=(s1-s2)/(d1-d2)
当d1!=d2,直接解出x,网络流判断
当d1==d2,假设当前全是x的状态是一个可行解,那么x+1也是。
所以可以考虑二分x,网络流判定
/************************************************************** Problem: 2756 User: zhouhebin Language: C++ Result: Accepted Time:7096 ms Memory:79436 kb ****************************************************************/ #include<cstdio> #include<iostream> #include<cstring> #define LL long long #define inf (1LL<<50) #define N 1610 #define S 0 #define T (n*m+1) #define pos(x,y) (x-1)*m+y using namespace std; int mx[4]={1,0,-1,0},my[4]={0,1,0,-1}; inline LL read() { LL x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int tt,n,m,cnt,Mx,s1,s2; LL sum1,sum2,l,r,tot,ans,QAQ; int a[55][55]; struct edge{int to,next;LL v;}e[5000000]; int head[N],q[N],h[N]; inline void ins(int u,int v,LL w) { e[++cnt].to=v; e[cnt].v=w; e[cnt].next=head[u]; head[u]=cnt; } inline void insert(int u,int v,LL w) { ins(u,v,w); ins(v,u,0); } inline bool bfs() { memset(h,-1,sizeof(h)); int t=0,w=1; q[0]=S;h[S]=0; while (t!=w) { int now=q[t++];if (t==1605)t=0; for (int i=head[now];i;i=e[i].next) if (e[i].v&&h[e[i].to]==-1) { h[e[i].to]=h[now]+1; q[w++]=e[i].to; if (w==1605)w=0; } } return h[T]!=-1; } inline LL dfs(int x,LL f) { if (x==T||!f)return f; LL w,used=0; for (int i=head[x];i;i=e[i].next) if (e[i].v&&h[e[i].to]==h[x]+1) { w=dfs(e[i].to,min(e[i].v,f-used)); e[i].v-=w; e[i^1].v+=w; used+=w; if (used==f)return f; } if (!used)h[x]=-1; return used; } inline void dinic(){while (bfs())ans+=dfs(S,inf);} inline void build(LL x) { ans=0;cnt=1;tot=0; memset(head,0,sizeof(head)); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if ((i+j)&1) { insert(S,pos(i,j),x-a[i][j]); for(int k=0;k<4;k++) { int nx=i+mx[k],ny=j+my[k]; if (nx<1||ny<1||nx>n||ny>m)continue; insert(pos(i,j),pos(nx,ny),inf); } tot+=x-a[i][j]; }else insert(pos(i,j),T,x-a[i][j]); } inline bool jud(LL x) { build(x); dinic(); return ans==tot; } inline void work() { n=read();m=read(); sum1=sum2=s1=s2=Mx=0; for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { a[i][j]=read(); Mx=max(Mx,a[i][j]); if ((i+j)&1)sum1+=a[i][j],s1++; else sum2+=a[i][j],s2++; } if(s1!=s2) { LL des=(sum1-sum2)/(s1-s2); if (des>=Mx&&jud(des))printf("%lld\n",ans); else printf("-1\n"); return; } QAQ=inf;l=Mx;r=2000000000; while (l<=r) { LL mid=(l+r)>>1; if (jud(mid))QAQ=min(QAQ,ans),r=mid-1; else l=mid+1; } printf("%lld\n",QAQ); } int main() { tt=read(); while (tt--)work(); return 0; }
——by zhber,转载请注明来源