【SCOI2012】【二分法】【最大流】奇怪的游戏
来源:互联网 发布:婚礼相册制作软件 编辑:程序博客网 时间:2024/05/14 00:22
这道题初看也许会感觉无法下手,由于每次操作都是相邻的两个,所以可以考虑将棋盘黑白染色,这样我们可以对黑色的格子和白色的格子单独考虑。
设黑色格子个数为cnt1,总和为sum1,白色格子个数为cnt2,总和为sum2,最终所有格子都变成了x,则很容易写出下列的关系式:
cnt1 * x - sum1 = cnt2 * x - sum2
=> x * (cnt1 - cnt2) = sum1 - sum2
=> x = (sum1 - sum2) / (cnt1 - cnt2)
现在讨论cnt1 与 cnt2的情况:
1、若cnt1 = cnt2,则说明在sum1 = sum2的情况下,若x可行,则x+1同样可以,这样我们可以通过二分的方法找出最小的满足条件的x,求出最小步数;若sum1 != sum2则无解。
2、若cnt1 != cnt2,则我们解出了一个x
这个x必须要满足三个条件:
(1)x必须为整数
(2)x不小于所有格子的最大值
(3)x必须要通过检验
如果x满足这三个条件,则我们可以解出最小步数,否则无解。
那么我们怎样检验x是否可行呢,这个需要通过网络流来验证。
设map[i][j]为格子对应的数字,对于每个黑色的格子,从源点连一条边,容量为x - map[i][j],并且对它周围的四个白色格子连一条边容量为inf;对于每个白色格子,向汇点连一条边,容量为x - map[i][j]
设最大流为maxflow,若maxflow = (n * m * x - sum1 - sum2) >> 1的话,说明存在方案可以使所有数变成x,同时最小步数minstep = (n * m * x - sum1 - sum2) >> 1
注意到格子的数可能很大,所以要使用long long类型
这样就解决了本题。
代码:
#include<cstdio>#include<cstring>using namespace std;const int maxn = 50;const int maxpoint = 3000;const int maxm = 100000;const long long inf = 0x3f3f3f3f3f3f3f3fll;struct Edge{int pos;long long c;int next;}E[maxm];int map[maxn][maxn],head[maxpoint];int dis[maxpoint],gap[maxpoint],cur[maxpoint],pre[maxpoint];int T,n,m;int NE,s,t,nodenum;long long maxw,cnt1,sum1,cnt2,sum2,com;void init(){freopen("bzoj2756.in","r",stdin);freopen("bzoj2756.out","w",stdout);}inline int max(long long a,long long b){return a > b ? a : b;}inline void checkmin(long long &a,long long b){if(a == -1 || a > b)a = b;}inline long long gettime(long long x){return (x * n * m - sum1 - sum2) >> 1;}void insert(int u,int v,long long c){E[NE].c = c;E[NE].pos = v;E[NE].next = head[u];head[u] = NE++;E[NE].c = 0;E[NE].pos = u;E[NE].next = head[v];head[v] = NE++;}long long sap(){memset(dis,0,sizeof(dis));memset(gap,0,sizeof(gap));for(int i = s;i <= t;i++)cur[i] = head[i];int u = pre[s] = s;long long maxflow = 0,aug = -1;gap[0] = nodenum;while(dis[s] < nodenum){loop: for(int &i = cur[u];i != -1;i = E[i].next) { int v = E[i].pos; if(E[i].c && dis[u] == dis[v] + 1) { checkmin(aug,E[i].c); pre[v] = u; u = v; if(v == t) { maxflow += aug; for(u = pre[u];v != s;v = u,u = pre[u]) { E[cur[u]].c -= aug; E[cur[u]^1].c += aug; } aug = -1; } goto loop; } } int mind = nodenum; for(int i = head[u];i != -1;i = E[i].next) { int v = E[i].pos; if(E[i].c && (mind > dis[v])) {cur[u] = i;mind = dis[v]; } } if(--(gap[dis[u]]) == 0)break; gap[dis[u] = mind + 1]++; u = pre[u];}return maxflow;}bool check(long long x){memset(E,0,sizeof(E));memset(head,-1,sizeof(head));NE = 0,s = 0,t = n * m + 1;nodenum = t + 1;for(int i = 1;i <= n;i++){for(int j = 1;j <= m;j++){if((i + j) & 1){insert(s,(i - 1) * m + j,x - map[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 - map[i][j]);}}return ((sap() << 1) == (x * n * m - sum1 - sum2));}void solve(){if(cnt1 != cnt2){if((sum1 - sum2) % (cnt1 - cnt2) != 0)printf("-1\n");else{long long x = (sum1 - sum2) / (cnt1 - cnt2);if(x < maxw){printf("-1\n");return;}if(check(x))printf("%lld\n",gettime(x));else printf("-1\n");}}else{long long l = maxw,r = inf;while(l < r){long long m = (l + r) >> 1;if(check(m))r = m;else l = m + 1;}if(check(r))printf("%lld\n",gettime(r));else printf("-1\n");}}void readdata(){scanf("%d",&T);while(T--){memset(map,0,sizeof(map));maxw = 0,sum1 = 0,cnt1 = 0,sum2 = 0,cnt2 = 0;scanf("%d%d",&n,&m);for(int i = 1;i <= n;i++){for(int j = 1;j <= m;j++){scanf("%d",&map[i][j]);if((i + j) & 1)cnt1++,sum1 += map[i][j];else cnt2++,sum2 += map[i][j];maxw = max(maxw,map[i][j]);}}solve();}}int main(){init();readdata();return 0;}
- 【SCOI2012】【二分法】【最大流】奇怪的游戏
- 【BZOJ2756】【SCOI2012】奇怪的游戏 最大流、
- 【最大流】【二分检验】【SCOI2012】奇怪的游戏
- 【二分+最大流】[SCOI2012]奇怪的游戏 BZOJ2756
- bzoj2756: [SCOI2012]奇怪的游戏 二分+最大流
- 【最大流】【二分】[Scoi2012] bzoj2756 奇怪的游戏
- 【bzoj2756】【SCOI2012】【奇怪的游戏】【最大流+二分】
- bzoj2756[SCOI2012]奇怪的游戏 二分 分类讨论 最大流
- Dinic最大流(bzoj 2756: [SCOI2012]奇怪的游戏)
- SCOI2012[奇怪的游戏]
- [SCOI2012]奇怪的游戏 (网络流)
- bzoj2756: [SCOI2012]奇怪的游戏
- [BZOJ2756][SCOI2012]奇怪的游戏
- BZOJ2756/SCOI2012 奇怪的游戏
- bzoj2756 [SCOI2012]奇怪的游戏
- bzoj2756 [SCOI2012]奇怪的游戏
- bzoj2756 [SCOI2012]奇怪的游戏
- 2756: [SCOI2012]奇怪的游戏
- [Android实例] Android中的坐标系统
- 不常使用的css3
- C#中override和overload的区别
- 抽象工厂 abstractFactory
- Linux /etc/passwd /etc/group /etc/shadow 文件的格式说明
- 【SCOI2012】【二分法】【最大流】奇怪的游戏
- 在Mac OS X中安装配置Apache + PHP + MySQL +Tomcat
- Hook Shadow SSDT
- jquery like library
- Unix命令大全
- 数据结构知识总结
- current thread not owner"错误的解决方法
- 浅析UPnP协议
- android recovery sda 设备号被占用,sdb无法再recovery中使用问题解决。