能量魔方

Time Limit: 10 Sec  Memory Limit: 64 MB
[Submit][Status][Discuss]

Description

  小C 有一个能量魔方,这个魔方可神奇了,只要按照特定方式,放入不同的 能量水晶,就可以产生巨大的能量。 能量魔方是一个 N*N*N 的立方体,一共用 N3 个空格可以填充能量水晶。 能量水晶有两种: ·一种是正能量水晶(Positive) ·一种是负能量水晶(Negative) 当这个魔方被填满后,就会依据填充的能量水晶间的关系产生巨大能量。对 于相邻两(相邻就是拥有同一个面)的两个格子,如果这两个格子填充的是一正一 负两种水晶,就会产生一单位的能量。而整个魔方的总能量,就是这些产生的能 量的总和。 现在,小 C 已经在魔方中填充了一些水晶,还有一些位置空着。他想知道, 如果剩下的空格可以随意填充,那么在最优情况下,这个魔方可以产生多少能量。

Input

  第一行包含一个数N,表示魔方的大小。 接下来 N2 行,每行N个字符,每个字符有三种可能: P:表示此方格已经填充了正能量水晶; N:表示此方格已经填充了负能量水晶; ?:表示此方格待填充。 上述 N*N 行,第(i-1)*N+1~i*N 行描述了立方体第 i 层从前到后,从左到右的 状态。且每 N 行间,都有一空行分隔。

Output

  仅包含一行一个数,表示魔方最多能产生的能量

Sample Input

  2
  P?
  ??
  
  ??
  N?

Sample Output

  9
  explain:
  PN 
  NP 
  
  NP 
  NN 

HINT

  n<=40

Main idea

  给出一个n*n*n的矩阵,其中每一个方块可以涂两种颜色,相邻的两个方块如果涂上的颜色不同,就会产生能量。已知了一些方块的颜色,询问最多可以的最多能量。

Solution

  发现n<=40,大胆猜测是个网络流。思考过后,发现直接求不好连边,那么我们考虑求出最小损耗,然后用(总收益)-(最小损耗)。

  由于相邻的才对答案有贡献,所以我们想到了黑白染色,将所有点划分为两类,那么显然将相邻的点都连一条双向边,权值为1。然后我们考虑如何处理已经规定的点,这时候可以令S集表示1,令T集表示0,将白点的1连向T权值为INF,将S连向黑点的1权值为INF,这样就可以表示不可选了,点权为0则相反。然后跑一遍最小割,计算即可。

Code

 #include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
#define ID(x,y,z) ((z-1)*n*n + (x-1)*n + y) const int ONE=;
const int TWO=;
const int INF=; int n,S,T;
char ch[ONE],c;
int a[][][];
int next[TWO],first[TWO],go[TWO],w[TWO],tot;
int q[],tou,wei;
int Dep[ONE],E[TWO];
int Ans; int get()
{
int res=,Q=;char c;
while( (c=getchar())< || c> )
if(c=='-')Q=-;
res=c-;
while( (c=getchar())>= && c<= )
res=res*+c-;
return res*Q;
} void Add(int u,int v,int z)
{
next[++tot]=first[u]; first[u]=tot; go[tot]=v; w[tot]=z;
next[++tot]=first[v]; first[v]=tot; go[tot]=u; w[tot]=;
} void Double_Add(int u,int v,int z)
{
Add(u,v,z);
Add(v,u,z);
} int PD(int x,int y,int z)
{
return (x+y+z)%;
} int Bfs()
{
memset(Dep,,sizeof(Dep));
tou=; wei=; Dep[]=; q[]=;
for(int u=;u<=T-;u++) E[u]=first[u];
while(tou<wei)
{
int u=q[++tou];
for(int e=first[u];e;e=next[e])
{
int v=go[e];
if(Dep[v] || !w[e]) continue;
Dep[v]=Dep[u]+;
q[++wei]=v;
}
}
return Dep[T]>;
} int Dfs(int u,int Limit)
{
if(u==T || !Limit) return Limit;
int flow=,f;
for(int &e=E[u];e;e=next[e])
{
int v=go[e];
if(Dep[v]!=Dep[u]+ || !w[e]) continue;
f=Dfs(v,min(Limit,w[e]));
w[e]-=f;
w[((e-)^)+]+=f;
Limit-=f;
flow+=f;
if(!Limit) break;
}
return flow;
} int main()
{
cin>>n; S=; T=n*n*n+;
for(int z=;z<=n;z++)
for(int x=;x<=n;x++)
{
scanf("%s",ch+);
for(int y=;y<=n;y++)
{
if(ch[y]=='?') a[x][y][z]=;
if(ch[y]=='P') a[x][y][z]=;
if(ch[y]=='N') a[x][y][z]=;
}
} for(int z=;z<=n;z++)
for(int x=;x<=n;x++)
for(int y=;y<=n;y++)
{
if(a[x+][y][z]) Double_Add(ID(x,y,z),ID(x+,y,z),),Ans++;
if(a[x][y+][z]) Double_Add(ID(x,y,z),ID(x,y+,z),),Ans++;
if(a[x][y][z+]) Double_Add(ID(x,y,z),ID(x,y,z+),),Ans++; if(a[x][y][z]==)
{
if(PD(x,y,z)) Add(S,ID(x,y,z),INF);
else Add(ID(x,y,z),T,INF);
} if(a[x][y][z]==)
{
if(PD(x,y,z)) Add(ID(x,y,z),T,INF);
else Add(S,ID(x,y,z),INF);
}
} while(Bfs())
{
Ans-=Dfs(S,INF);
} printf("%d",Ans);
}

【BZOJ1976】能量魔方 [最小割]的更多相关文章

  1. 【二分 最小割】cf808F. Card Game

    Digital collectible card games have become very popular recently. So Vova decided to try one of thes ...

  2. 【BZOJ1976】[BeiJing2010组队]能量魔方 Cube 最小割

    [BZOJ1976][BeiJing2010组队]能量魔方 Cube Description 小C 有一个能量魔方,这个魔方可神奇了,只要按照特定方式,放入不同的 能量水晶,就可以产生巨大的能量. 能 ...

  3. 【BZOJ-1976】能量魔方Cube 最小割 + 黑白染色

    1976: [BeiJing2010组队]能量魔方 Cube Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 884  Solved: 307[Submi ...

  4. 【bzoj1976】[BeiJing2010组队]能量魔方 Cube 网络流最小割

    题目描述 一个n*n*n的立方体,每个位置为0或1.有些位置已经确定,还有一些需要待填入.问最后可以得到的 相邻且填入的数不同的点对 的数目最大. 输入 第一行包含一个数N,表示魔方的大小. 接下来 ...

  5. Bzoj 1976: [BeiJing2010组队]能量魔方 Cube 最小割,最大流

    1976: [BeiJing2010组队]能量魔方 Cube Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 879  Solved: 304[Submi ...

  6. BZOJ 1976 能量魔方 Cube(最小割)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1976 题意:给出一个n*n*n的立方体.每个小单位为字母P或者字母N.相邻两个小单位字母 ...

  7. BZOJ1976: [BeiJing2010组队]能量魔方 Cube

    1976: [BeiJing2010组队]能量魔方 Cube Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 832  Solved: 281[Submi ...

  8. 二分图&网络流&最小割等问题的总结

    二分图基础: 最大匹配:匈牙利算法 最小点覆盖=最大匹配 最小边覆盖=总节点数-最大匹配 最大独立集=点数-最大匹配 网络流: 技巧: 1.拆点为边,即一个点有限制,可将其转化为边 BZOJ1066, ...

  9. 基于模糊聚类和最小割的层次化网格分割算法(Hierarchical Mesh Decomposition)

    网格分割算法是三维几何处理算法中的重要算法,具有许多实际应用.[Katz et al. 2003]提出了一种新型的层次化网格分割算法,该算法能够将几何模型沿着凹形区域分割成不同的几何部分,并且可以避免 ...

随机推荐

  1. ArcGIS Server远程处理服务器(环境设置)

    当使用ArcGIS Server做远程处理服务器执行影像处理操作时,提示ERROR 999999通用错误代码,如下: Start Time: Mon Jul 03 13:49:06 2017Distr ...

  2. Sumsets 递推

    Sumsets Time Limit : 6000/2000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submi ...

  3. [P2387魔法森林

    题面 题意: 给出一个图,边权有两维,a与b. 求1到n的一条路径使得路径经过的边的最大的a与b的和最小,输出最小之和. \(Solution:\) 如果做过这题,那么就显得很简单了很好想了. 又是想 ...

  4. 以太坊 生成助记词和infuru插件

    https://iancoleman.io/bip39/ https://infura.io google faucet : https://faucet.rinkeby.io/ 登录google账号 ...

  5. wampserver 安装后 启动失败的解决方法

    安装后启动, 显示 发生未知的异常 wampmanager.exe  .... 解决方法 === 其实下载页面说了,先下载 vc的运行库,页面上有链接, 他给的是vc10的,我按照做,失败 查了无数资 ...

  6. 通过 systemctl 设置自定义 Service

    如果要在Linux 上设置一个开机自启,出现问题自动重启,并且有良好日志的程序,比较流行的方法有 supervisord.systemd,除此之外,还有 upstart.runit 等类似的工具. 但 ...

  7. BZOJ 4184 shallot 线性基+分治

    Description 小苗去市场上买了一捆小葱苗,她突然一时兴起,于是她在每颗小葱苗上写上一个数字,然后把小葱叫过来玩游戏. 每个时刻她会给小葱一颗小葱苗或者是从小葱手里拿走一颗小葱苗,并且让小葱从 ...

  8. 最短路径——Bellman-Ford算法

    一.相关定义 最短路径:求源点到某特定点的最短距离 特点:Bellman-Ford算法主要是针对有负权值的图,来判断该图中是否有负权回路或者存在最短路径的点 局限性:算法效率不高,不如SPFA算法 时 ...

  9. [剑指Offer] 23.二叉搜索树的后序遍历

    [思路]BST的后序序列的合法序列是,对于一个序列S,最后一个元素是x (也就是根),如果去掉最后一个元素的序列为T,那么T满足:T可以分成两段,前一段(左子树)小于x,后一段(右子树)大于x,且这两 ...

  10. RadioGroup 的使用

    //获取 RadioGroup 项目名称 procedure TForm1.RadioGroup1Click(Sender: TObject); begin   Text := RadioGroup1 ...