hdu5076
好题,首先观察可得w[i][j]选择只有可能两种,一种比阀值大,一种比阀值小
比阀值大就一定选满足条件最大的w,比阀值小同样一定选满足条件最大的w
那么一个最小割模型就呼之欲出了,注意w可能是负数那么就集体+1025;
我们把这两种情况分辨记作w[i][mx[i]],w[i][mi[i]]
下面是建图,观察两个byte产生收益是or条件似乎不好处理
但仔细观察连边条件可以发现,二进制只有1位不同意味着byte编号一定可以构成一个二分图
于是,对于二进制所含1的个数为奇数的i,连边(s,i,w[i][mi[i]]),(i,t,w[i][mx[i]]),而对二进制所含1的个数为偶数的数j则相反
额外收益即可表示为(i,j,u[i]^u[j])
那么最大分数=总分数-最小割-n*1025;
下面就是构造方案了,我一开始sb wa了很久
首先有的w[i]中不存在比阀值小的情况,那这些byte分配什么value是确定的
做完最小割后,我们从s沿残流网络做一遍dfs,如果s可以走到i,就意味着(s,i)的边可以不割,(i,t)的边要割
那么对应点如何选择也就出来了
#include<bits/stdc++.h> using namespace std;
struct way{int flow,po,next;} e[];
int p[],numh[],h[],cur[],pre[],d[],cl[],w[][],mx[],mi[],ans[],u[],b[];
bool v[];
int n,m,ln,lm,len,t;
const int lim=;
const int inf=; void add(int x,int y,int f)
{
e[++len].po=y;
e[len].flow=f;
e[len].next=p[x];
p[x]=len;
}
void build(int x, int y, int f)
{
add(x,y,f);
add(y,x,);
} int sap()
{
memset(h,,sizeof(h));
memset(numh,,sizeof(numh));
numh[]=t+;
for (int i=; i<=t; i++) cur[i]=p[i];
int j,u=,s=,neck=inf;
while (h[]<t+)
{
d[u]=neck;
bool ch=;
for (int i=cur[u]; i!=-; i=e[i].next)
{
j=e[i].po;
if (e[i].flow>&&h[u]==h[j]+)
{
neck=min(neck,e[i].flow);
cur[u]=i;
pre[j]=u; u=j;
if (u==t)
{
s+=neck;
while (u)
{
u=pre[u];
j=cur[u];
e[j].flow-=neck;
e[j^].flow+=neck;
}
neck=inf;
}
ch=;
break;
}
}
if (ch)
{
if (--numh[h[u]]==) return s;
int q=-,tmp=t;
for (int i=p[u]; i!=-; i=e[i].next)
{
j=e[i].po;
if (e[i].flow&&h[j]<tmp)
{
tmp=h[j];
q=i;
}
}
cur[u]=q; h[u]=tmp+;
numh[h[u]]++;
if (u)
{
u=pre[u];
neck=d[u];
}
}
}
return s;
} bool dfs(int x)
{
v[x]=;
for (int i=p[x]; i>-; i=e[i].next)
{
int y=e[i].po;
if (!e[i].flow) continue;
if (!v[y]) dfs(y);
}
} int main()
{
int cas;
scanf("%d",&cas);
for (int i=; i<; i++)
{
for (int j=; j< ;j++)
cl[i]^=(i>>j)&;
}
while (cas--)
{
scanf("%d%d",&ln,&lm);
n=<<ln; m=<<lm;
len=-; memset(p,,sizeof(p));
memset(ans,,sizeof(ans));
for (int i=; i<=n; i++) scanf("%d",&b[i]);
for (int i=; i<=n; i++) scanf("%d",&u[i]);
for (int i=; i<=n; i++)
{
mi[i]=mx[i]=;
w[i][]=-lim; b[i]++;
for (int j=; j<b[i]; j++)
{
scanf("%d",&w[i][j]);
if (w[i][mi[i]]<w[i][j]) mi[i]=j;
}
for (int j=b[i]; j<=m; j++)
{
scanf("%d",&w[i][j]);
if (w[i][mx[i]]<w[i][j]) mx[i]=j;
}
if (!mi[i]) ans[i]=mx[i];
}
t=n+;
for (int i=; i<n; i++)
if (cl[i])
{
for (int j=; j<ln; j++)
{
int y=i^(<<j);
build(i+,y+,u[i+]^u[y+]);
}
}
for (int i=; i<=n; i++)
if (cl[i-])
{
build(,i,w[i][mi[i]]+lim);
build(i,t,w[i][mx[i]]+lim);
}
else {
build(,i,w[i][mx[i]]+lim);
build(i,t,w[i][mi[i]]+lim);
}
sap();
memset(v,,sizeof(v));
dfs();
for (int i=p[]; i>-; i=e[i].next)
{
int x=e[i].po;
if (ans[x]) continue;
if ((v[x]&&cl[x-])||(!v[x]&&!cl[x-])) ans[x]=mi[x];
else ans[x]=mx[x];
}
for (int i=; i<=n; i++)
{
printf("%d",ans[i]-);
if (i!=n) printf(" "); else puts("");
}
}
}
hdu5076的更多相关文章
随机推荐
- C语言单元测试
转自http://blog.csdn.net/colin719/article/details/1420583 对于敏捷开发来说,单元测试必不可少,对于Java开发来说,JUnit非常好,对于C++开 ...
- linux启动和关闭防火墙命令
在此说一下关于启动和关闭防火墙的命令:1) 重启后生效开启: chkconfig iptables on关闭: chkconfig iptables off2) 即时生效,重启后失效开启: servi ...
- 封装 RabbitMQ.NET
这篇文章内容会很短,主要是想给大家分享下我最近在做一个简单的rabbitmq客户端类库的封装的经验总结,说是简单其实一点都不简单.为了节省时间我主要按照Library的执行顺序来介绍,在你看来这里仅仅 ...
- Param指南
param name标签是在这个播放插件中嵌入的一些功能和播放参数: <param name="playcount" value="1"><! ...
- hdu 3172 Virtual Friends (并查集)
Virtual Friends Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- 正式进军Matlab图像处理
Matlab取整函数有:fix, floor, ceil, round,具体应用方法如下: 1. fix朝零方向取整,如fix(-1.3) = -1; fix(1.3) = 1; 2. floor顾名 ...
- 【题解】[USACO12JAN]视频游戏的连击Video Game Combos
好久没有写博客了,好惭愧啊……虽然这是一道弱题但还是写一下吧. 这道题目的思路应该说是很容易形成:字符串+最大值?自然联想到学过的AC自动机与DP.对于给定的字符串建立出AC自动机,dp状态dp[i] ...
- [洛谷P3195][HNOI2008]玩具装箱TOY
题目大意:有n个物体,大小为$c_i$.把第i个到第j个放到一起,容器的长度为$x=j-i+\sum\limits_{k-i}^{j} c_k$,若长度为x,费用为$(x-L)^2$.费用最小. 题解 ...
- OSI 七层模型和 TCP/IP 四层模型 及 相关网络协议
简介 OSI 是理论上的模型,也就是一个统一的国际标准,现在的很多网络设备或者是网络协议都不同程度的精简了自己的所谓的模型,那么他们为了自己的通讯兼容都会参考这个OSI模型 TCP/IP 包括: TC ...
- tcp/ip网络协议学习
链路层介绍 网络层协议的数据单元是 IP 数据报 ,而数据链路层的工作就是把网络层交下来的 IP 数据报 封装为 帧(frame)发送到链路上,以及把接收到的帧中的数据取出并上交给网络层. 以太网 以 ...