能量魔方

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. Ubuntu中搭建Hadoop集群(简记)

    stp1:在Vmware虚拟机上创建Ubantu.2环境 步骤:文件—>新建虚拟机—>典型(下一步)—>下一步——>位置(不建议放c盘,文件地址一定要全英文)—>下一步— ...

  2. iOS下原生与JS交互(总结)

    iOS开发免不了要与UIWebView打交道,然后就要涉及到JS与原生OC交互,今天总结一下JS与原生OC交互的两种方式. JS调用原生OC篇(我自己用的方式二,简单方便) 方式一 第一种方式是用JS ...

  3. deepin linux 安装/启动jeakins报错:处理

    ERROR: No Java executable found in current PATH: /bin:/usr/bin:/sbin:/usr/sbin 安装报错: 1.如还未安装java,则安装 ...

  4. C++类数组批量赋值

    类和结构体不同,结构体在初始化时可以使用{...}的方法全部赋值,但是结构体怎么办呢?一种是把数据数组写到一个相同的结构体内,然后for循环使用一个非构造函数写入到类数组中.另一种方法是直接写入到对应 ...

  5. 1034 Head of a Gang (30 分)(图的遍历or并查集)

    dfs #include<bits/stdc++.h> using namespace std; ; int mp[N][N]; int weight[N]; int vis[N]; ma ...

  6. Django,Celery, rabbitmq

    学习Django 2 by Example书中的456页,运行 celery -A myshop worker -l info 报错.虽然特别指定了Celery的版本,也没用.之前使用的是标准安装:下 ...

  7. MySQL统计数据库大小

    select concat(truncate(sum(data_length)/1024/1024,2),'mb') as data_size, concat(truncate(sum(max_dat ...

  8. yii视频地址哦

    https://www.yiichina.com/video  

  9. vue中表单的动态绑定

    有一个表单: <el-form :model="configForm"> </el-form> 如果configForm初始化为{},此对象是动态变化的,如 ...

  10. java enum naming rules & Pascal case, Camel case, Uppercase

    java enum naming rules Constant & all Capital Case https://stackoverflow.com/questions/3069743/c ...