能量魔方

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. C语言RL78 serial bootloader和C#语言bootloader PC端串口通信程序

    了解更多关于bootloader 的C语言实现,请加我QQ: 1273623966 (验证信息请填 bootloader),欢迎咨询或定制bootloader(在线升级程序). 前段时间完成的hype ...

  2. php杂记——1(基础知识与文件读写)

    1.变量前面需要加美元符号"$",常量则不需要: define('PRICE',100); echo PRICE; 2.用一个变量的值作为另一个变量的名称可以得到类似C中的指针变量 ...

  3. 在spring+beranate中多数据源中使用 ThreadLocal ,总结的原理 --费元星

    设计模式 首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问 ...

  4. PHP批量替换MySql数据库中的数据内容

    <?php //替换数据库内容类 class replace{ public $dbAddress; //数据库地址 public $dbUser; //数据库用户名 public $dbPwd ...

  5. XenServer设置master,摧毁故障主机

    XenServer pool 移除server 设置master 这分为Pool Master是正常还是异常2种情况: 正常情况下可能要对Pool Master做一些停机维护,比如换内存条啥的,此时在 ...

  6. NSDictionary底层实现原理

    一言以蔽之:在OC中NSDictionary是使用hash表来实现key和value的映射和存储的. 那么问题来了什么是hash表呢? 哈希表(hash表): 又叫做散列表,是根据关键码值(key v ...

  7. Python 3基础教程29-os模块

    本文介绍os模块,主要是介绍一些文件的相关操作. 你还有其他方法去查看os 1. help() 然后输入os 2. Python接口文档,前面提到的用浏览器打开的,os文件路径为:C:\Users\A ...

  8. PAT——甲级1012:The Best Rank(有坑)

    1012 The Best Rank (25 point(s)) To evaluate the performance of our first year CS majored students, ...

  9. union的代码有点难理解额

    union跟位域都可以节省内存,而且union在某些地方还能起到更好看的效果? 比如: struct Matrix { union { struct { float _f11, _f12, _f13, ...

  10. 服务追踪数据使用 RabbitMQ 进行采集 + 数据存储使用 Elasticsearch + 数据展示使用 Kibana

    服务追踪数据使用 RabbitMQ 进行采集 + 数据存储使用 Elasticsearch + 数据展示使用 Kibana https://www.cnblogs.com/xishuai/p/elk- ...