题目描述

  Bob有\(2^n\)字节的内存,编号为\([0,2^n-1)\)。他想对每个字节的内存分别分配一个值。对于编号为\(i\)的内存,如果它被分配了一个值\(j(0\leq j<2^m)\),那么该字节产生的基本欢乐值为\(w_{i,j}\)。

  更欢乐的是,每一个字节还有一个临界值\(c_i\)。对于两个不同的字节,编号分别为\(a,b(a<b)\),如果以下两个条件同时成立,那么就会产生额外欢乐值\(u_a\text{^}u_b\)。

  1.在二进制下,\(a\)和\(b\)有且仅有一位不同(例如\(4\)和\(5\),\(4\)的二进制为\(100\),\(5\)的二进制为\(101\),有且仅有第\(3\)位不同)。

  2.在\(a\)字节分配的值不少于\(a\)字节的临界值\(c_a\),或者在\(b\)字节分配的值不少于\(b\)字节的临界值\(c_b\)。

  一种分配方法的总欢乐值是每个字节的基本欢乐值的总和加上额外欢乐值。

  Bob想找到一种最佳分配方法,使得总欢乐值最大。如果有多组解,请任意输出一种。

  \(1\leq n,m\leq 8,0\leq c_i<2^m,0\leq u_i<1024,-1024\leq w_{i,j}<1024\)

题解

  对于一个字节的内存\(i\),分配的值只可能是两个,\(j<c_i\)和\(j\geq c_i\)的使\(w_{i,j}\)最大的\(j\),分别是\(v1_i,v2_i\)。

  因为对于每一组满足条件的\(a,b\),只有两个位置都小于\(c_a,c_b\)时才没有收益。可以看出这是一个最小割的模型,割就是要放弃的收益。

  但是还有一个问题,两个点都割掉左边的边才有额外代价,这就会出现问题。我们观察一下一般的棋盘是怎么解决这个问题的:黑白染色。那么这个问题能不能用类似的方法做呢?答案是可以。因为两个不同的点连边的条件是二进制位相差\(1\),这样连边是不会出现奇环的,所以我们可以把二进制中\(1\)的个数为奇数的点反过来连边

  所以连边方案就变成了:

  1.如果\(i\)的二进制中\(1\)的个数为奇数,就连边\((S,i,v1_i)\),割掉这条边代表选择\(v2_i\)。同样的,连边\((i,T,v2_i)\)。

  2.如果\(i\)的二进制中\(1\)的个数为偶数,就连边\((S,i,v2_i)\)和\((i,T,v1_i)\)。

  3.如果\(a,b\)满足\(a\)的二进制中\(1\)的个数是奇数,\(b\)的二进制中\(1\)的个数是偶数,就连边\((a,b,u_a\text{^}u_b)\)。这条边只有在\((S,a)\)和\((b,T)\)都被选择,即选择\(v1_a\)和\(v1_b\)的情况下才会被选中。

  然后跑网络流,用边权和减掉流量就是答案。

  那么会有几个问题。

  1.怎么算每个点选那边?从原点开始BFS,遍历到的点都选另一边(即\((i,T)\)对应的方案),没遍历到的点选这一边(\((S,i)\))。

  2.怎么算每个点分配什么值?从大到小枚举,第一个满足条件的就是答案。因为\(w_{i,j}\)相同的情况下选\(j\)比较大的不会比选\(j\)比较小的劣。

  3.边权可能是负数。因为所有边权都\(\geq-1024\),可以把所有边权都加上一个\(\geq1024\)的数。

  时间复杂度:\(O(???)\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
struct list
{
int v[100010];
int c[100010];
int t[100010];
int h[100010];
int n;
list()
{
memset(h,0,sizeof h);
n=0;
}
void add(int x,int y,int z)
{
n++;
v[n]=y;
c[n]=z;
t[n]=h[x];
h[x]=n;
}
};
list l;
void add(int x,int y,int z)
{
l.add(x,y,z);
l.add(y,x,0);
}
int op(int x)
{
return ((x-1)^1)+1;
}
int d[1<<9];
int S,T;
int bfs()
{
memset(d,-1,sizeof d);
d[S]=0;
queue<int> q;
q.push(S);
while(!q.empty())
{
int x=q.front();
q.pop();
int i;
for(i=l.h[x];i;i=l.t[i])
if(l.c[i]&&d[l.v[i]]==-1)
{
d[l.v[i]]=d[x]+1;
if(l.v[i]==T)
return 1;
q.push(l.v[i]);
}
}
return 0;
}
int dfs(int x,int flow)
{
if(x==T)
return flow;
int c,s=0;
int i;
for(i=l.h[x];i;i=l.t[i])
if(l.c[i]&&d[l.v[i]]==d[x]+1)
{
c=dfs(l.v[i],min(flow,l.c[i]));
s+=c;
flow-=c;
l.c[i]-=c;
l.c[op(i)]+=c;
if(!flow)
break;
}
if(flow)
d[x]=-1;
return s;
}
int w[1<<9][1<<9];
int u[1<<9];
int c[1<<9];
int v1[1<<9];
int v2[1<<9];
int ans[1<<9];
int b[1<<9];
int bitcount(int x)
{
int s=0;
while(x)
{
x-=x&-x;
s++;
}
return s;
}
int main()
{
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
int n,m;
scanf("%d%d",&n,&m);
int i,j;
for(i=1;i<=(1<<n);i++)
scanf("%d",&c[i]);
for(i=1;i<=(1<<n);i++)
scanf("%d",&u[i]);
memset(v1,0x80,sizeof v1);
memset(v2,0x80,sizeof v2);
for(i=1;i<=(1<<n);i++)
for(j=0;j<(1<<m);j++)
{
scanf("%d",&w[i][j]);
if(j<c[i])
v1[i]=max(v1[i],w[i][j]);
else
v2[i]=max(v2[i],w[i][j]);
}
for(i=1;i<=(1<<n);i++)
b[i]=bitcount(i-1);
S=(1<<n)+1;
T=(1<<n)+2;
int sum=0;
for(i=1;i<=(1<<n);i++)
if(b[i]&1)
{
if(v1[i]>-2000)
add(S,i,v1[i]+2000);
if(v2[i]>-2000)
add(i,T,v2[i]+2000);
for(j=1;j<=(1<<n);j++)
if(bitcount((i-1)^(j-1))==1)
add(i,j,u[i]^u[j]);
}
else
{
if(v2[i]>-2000)
add(S,i,v2[i]+2000);
if(v1[i]>-2000)
add(i,T,v1[i]+2000);
}
int s=0;
while(bfs())
s+=dfs(S,0x7fffffff);
for(i=1;i<=(1<<n);i++)
if((d[i]==-1)^(b[i]&1))
ans[i]=v1[i];
else
ans[i]=v2[i];
for(i=1;i<=(1<<n);i++)
for(j=(1<<m)-1;j>=0;j--)
if(w[i][j]==ans[i])
{
printf("%d ",j);
break;
}
return 0;
}

【XSY1081】随机存储器 网络流的更多相关文章

  1. plain framework 1 网络流 缓存数据详解

    网络流是什么?为什么网络流中需要存在缓存数据?为什么PF中要采用缓存网络数据的机制?带着这几个疑问,让我们好好详细的了解一下在网络数据交互中我们容易忽视以及薄弱的一块.该部分为PF现有的网络流模型,但 ...

  2. 网络流模板 NetworkFlow

    身边的小伙伴们都在愉快地刷网络流,我也来写一发模板好了. Network Flow - Maximum Flow Time Limit : 1 sec, Memory Limit : 65536 KB ...

  3. COGS732. [网络流24题] 试题库

    «问题描述:假设一个试题库中有n道试题.每道试题都标明了所属类别.同一道题可能有多个类别属性.现要从题库中抽取m 道题组成试卷.并要求试卷包含指定类型的试题.试设计一个满足要求的组卷算法.«编程任务: ...

  4. ACM/ICPC 之 有流量上下界的网络流-Dinic(可做模板)(POJ2396)

    //有流量上下界的网络流 //Time:47Ms Memory:1788K #include<iostream> #include<cstring> #include<c ...

  5. BZOJ 3144 [Hnoi2013]切糕 ——网络流

    [题目分析] 网络流好题! 从割的方面来考虑问题往往会得到简化. 当割掉i,j,k时,必定附近的要割在k-D到k+D上. 所以只需要建两条inf的边来强制,如果割不掉强制范围内的时候,原来的边一定会换 ...

  6. bzoj3572又TM是网络流

    = =我承认我写网络流写疯了 = =我承认前面几篇博文都是扯淡,我写的是垃圾dinic(根本不叫dinic) = =我承认这道题我调了半天 = =我承认我这道题一开始是T的,后来换上真正的dinic才 ...

  7. hdu3549还是网络流

    最后一次训练模板(比较熟练了) 接下来训练网络流的建图 #include <cstdio> #define INF 2147483647 int n,m,ans,x,y,z,M,h,t,T ...

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

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

  9. COGS743. [网络流24题] 最长k可重区间集

    743. [网络流24题] 最长k可重区间集 ★★★   输入文件:interv.in   输出文件:interv.out   简单对比时间限制:1 s   内存限制:128 MB «问题描述: «编 ...

随机推荐

  1. 页面添加iconfont字体-[超详细]-支持彩色

    第一步: 去矢量图官网注册一下,获取小图标(字体) 的来源 (也可以是其他类似的网站)这里以 阿里妈妈矢量图 官网为例,因为图标丰富,方便使用. 注册请点:https://www.iconfont.c ...

  2. Pytest+Allure定制报告

    前言: 最近在研究接口自动化的框架,好的测试报告在整个测试框架起到至关重要的部分.终于被我发现一个超好用的报告框架,不仅报告美观,而且方便CI集成. 就是它,就是它:Allure Test Repor ...

  3. ACM-ICPC 2018 沈阳赛区网络预赛-I模拟题啊!!!

    垃圾题,题目巨TM长...这题题意就是说给你一个16进制串,让你把每一位转成长度为4的2进制数,并把这些数连接起来,连接完成后,进行奇偶校验,把字符串切割成每个长度为9的字符串,然后计算前8位的 1的 ...

  4. 295B - Greg and Graph (floyd逆序处理)

    题意:给出任意两点之间的距离,然后逐个删除这些点和与点相连的边,问,在每次删除前的所有点对的最短距离之和 分析:首先想到的是floyd,但是如果从前往后处理,复杂度是(500)^4,超时,我们从后往前 ...

  5. Json详解以及fastjson使用教程

    Json是一种轻量级的数据交换格式,采用一种“键:值”对的文本格式来存储和表示数据,在系统交换数据过程中常常被使用,是一种理想的数据交换语言.在使用Java做Web开发时,不可避免的会遇到Json的使 ...

  6. Chrome---谷歌浏览器修改用户缓存文件夹 如何设置缓存路径

    1.首先我们在电脑上打开chrome浏览器,然后地址栏输入chrome://Version,然后按下回车键,找到个人资料路径一项. 2.接下来我们选中个人资料路径后面所有的信息,右键点击信息后选择“复 ...

  7. Object.prototype.toString.call()

    源码中有这样一段: class2type = {}, toString = class2type.toString,   function type(obj) { //obj为null或者undefi ...

  8. 第六周作业----PSP&工作量

    1. PSP 日期 类别 工作 开始时间 中断时间 结束时间 总时间 4.7 站立会议 "耐撕"团队站立会议 20:00   20:15 15   重构 重构"抢答器&q ...

  9. python之路--基础数据类型的补充与深浅copy

    一 . join的用法 lst =['吴彦祖','谢霆锋','刘德华'] s = '_'.join(lst) print(s) # 吴彦祖_谢霆锋_刘德华 # join() "*" ...

  10. echo "" > 和 echo "" >> 的区别

    在写shell脚本中,如果判断一个文件已经存在,但希望重写这个文件,一般用如下方式 echo "" > file.txt 这个表示清空文件的内容,如果使用 echo “” & ...