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的更多相关文章
随机推荐
- 在es中用scroll查询与completableFuture
一般而言,es返回数据的上限是10000条,如果超过这个数量,就必须使用scroll查询. 所谓scroll查询就类似DBMS中的游标,或者快照吧,利用查询条件,在第一次查询时,在所有的结果上形成了一 ...
- BZOJ4570 SCOI2016妖怪(三分)
strength=atk*(1+b/a)+dnf*(1+a/b).设a/b=x,可以发现这是一个关于x的对勾函数.开口向上的一堆凸函数取max还是凸函数,三分即可. 然而无良出题人既卡精度又卡时间.众 ...
- P1268 树的重量
题目描述 树可以用来表示物种之间的进化关系.一棵“进化树”是一个带边权的树,其叶节点表示一个物种,两个叶节点之间的距离表示两个物种的差异.现在,一个重要的问题是,根据物种之间的距离,重构相应的“进化树 ...
- TCP/IP Note1
TCP/IP(Transmission Control Protocol / Internet Protocol)是用于Internet的通信协议. 计算机通信协议:是指对那些计算机必须遵守以便彼此通 ...
- 使用 URLDecoder 和 URLEncoder 对中文字符进行编码和解码
原文: https://blog.csdn.net/justloveyou_/article/details/57156039 使用 URLDecoder 和 URLEncoder 对中文字符进行编码 ...
- Codeforces Round #526 (Div. 2) E. The Fair Nut and Strings
E. The Fair Nut and Strings 题目链接:https://codeforces.com/contest/1084/problem/E 题意: 输入n,k,k代表一共有长度为n的 ...
- fastjson解析服务端返回的数据
1.配置依赖 //fastjson api 'com.alibaba:fastjson:1.2.44' 2.设计服务端返回的数据 {},{},{}]} 3.编写bean类,特别注意,要和服务端返回的类 ...
- libusb 示例
#include <usb.h> #include <stdio.h> #define VERSION "0.1.0" #define VENDOR_ID ...
- bzoj 2525 [Poi2011]Dynamite 二分+树形dp
[Poi2011]Dynamite Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 270 Solved: 138[Submit][Status][D ...
- vue+koa+mysql简易demo
功能支持网址收藏编辑 代码: https://github.com/lanleilin/lanOdyssey/tree/master/vueKoa/webCollection1 运行方法: 在serv ...