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的更多相关文章
随机推荐
- J2EE开发实战基础系列一 HelloWorld
开始咱们的第一个程序,首先是配置环境,按照上一章所描述的方式下载开发工具,然后配置Java环境变量,给大家看下具体的结构: 环境变量配置OK的提示,如上图. Eclipse和Tomcat的文件目录位置 ...
- Android 多屏幕适配 dp和px的关系
一直以来别人经常问我,android的多屏幕适配到底是怎么弄,我也不知道如何讲解清楚,或许自己也是挺迷糊. 以下得出的结论主要是结合官方文档进行分析的https://developer.android ...
- [剑指Offer] 24.二叉树中和为某一值的路径
[思路] ·递归先序遍历树, 把结点加入路径. ·若该结点是叶子结点则比较当前路径和是否等于期待和. ·弹出结点,每一轮递归返回到父结点时,当前路径也应该回退一个结点 注:路径定义为从树的根结点开始往 ...
- 自定义 Relam
package org.zln.hello.realm; import org.apache.shiro.authc.*; import org.apache.shiro.realm.Realm; / ...
- elasticsearch集群及filebeat server和logstash server
elasticsearch集群及filebeat server和logstash server author:JevonWei版权声明:原创作品blog:http://119.23.52.191/ 实 ...
- 【loj6177】「美团 CodeM 初赛 Round B」送外卖2 Floyd+状压dp
题目描述 一张$n$个点$m$条边的有向图,通过每条边需要消耗时间,初始为$0$时刻,可以在某个点停留.有$q$个任务,每个任务要求在$l_i$或以后时刻到$s_i$接受任务,并在$r_i$或以前时刻 ...
- [NOIP2018 TG D1T3]赛道修建
题目大意:$NOIP2018\;TG\;D1T3$ 题解:题目要求最短的赛道的长度最大,可以想达到二分答案,接着就是一个显然的树形$DP$. 发现对于一个点,它子树中若有两条链接起来比要求的答案大,一 ...
- [51nod1482]部落信号 单调栈
~~~题面~~~ 题解: 可以发现这是一道单调栈的题目,首先来考虑数字没有重复时如何统计贡献. 因为这是一个环,而如果我们从最高的点把环断开,并把最高点放在链的最后面(顺时针移动),那么因为在最高点两 ...
- eclipse调试java技巧
详细内容请看: http://www.oschina.net/question/82993_69439
- vue之axios使用
axios是vue-resource后出现的Vue请求数据的插件.vue更新到2.0之后,作者尤大就宣告不再对vue-resource更新,而是推荐的axios. 下面我们来使用axios npm i ...