好题,首先观察可得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)的边要割

那么对应点如何选择也就出来了

  1 #include<bits/stdc++.h>
  2 
  3 using namespace std;
  4 struct way{int flow,po,next;} e[600010];
  5 int p[610],numh[610],h[610],cur[610],pre[610],d[610],cl[610],w[610][610],mx[610],mi[610],ans[610],u[610],b[610];
  6 bool v[610];
  7 int n,m,ln,lm,len,t;
  8 const int lim=1025;
  9 const int inf=1000000007;
 10 
 11 void add(int x,int y,int f)
 12 {
 13      e[++len].po=y;
 14      e[len].flow=f;
 15      e[len].next=p[x];
 16      p[x]=len;
 17 }
 18 void build(int x, int y, int f)
 19 {
 20      add(x,y,f);
 21      add(y,x,0);
 22 }
 23 
 24 int sap()
 25 {
 26     memset(h,0,sizeof(h));
 27     memset(numh,0,sizeof(numh));
 28     numh[0]=t+1;
 29     for (int i=0; i<=t; i++) cur[i]=p[i];
 30     int j,u=0,s=0,neck=inf;
 31     while (h[0]<t+1)
 32     {
 33           d[u]=neck;
 34           bool ch=1;
 35           for (int i=cur[u]; i!=-1; i=e[i].next)
 36           {
 37               j=e[i].po;
 38               if (e[i].flow>0&&h[u]==h[j]+1)
 39               {
 40                  neck=min(neck,e[i].flow);
 41                  cur[u]=i;
 42                  pre[j]=u;  u=j;
 43                  if (u==t)
 44                  {
 45                     s+=neck;
 46                     while (u)
 47                     {
 48                           u=pre[u];
 49                           j=cur[u];
 50                           e[j].flow-=neck;
 51                           e[j^1].flow+=neck;
 52                     }
 53                     neck=inf;
 54                  }
 55                  ch=0;
 56                  break;
 57               }
 58           }
 59           if (ch)
 60           {
 61              if (--numh[h[u]]==0) return s;
 62              int q=-1,tmp=t;
 63              for (int i=p[u]; i!=-1; i=e[i].next)
 64              {
 65                  j=e[i].po;
 66                  if (e[i].flow&&h[j]<tmp)
 67                  {
 68                     tmp=h[j];
 69                     q=i;
 70                  }
 71              }
 72              cur[u]=q; h[u]=tmp+1;
 73              numh[h[u]]++;
 74              if (u)
 75              {
 76                 u=pre[u];
 77                 neck=d[u];
 78              }
 79           }
 80     }
 81     return s;
 82 }
 83 
 84 bool dfs(int x)
 85 {
 86     v[x]=1;
 87     for (int i=p[x]; i>-1; i=e[i].next)
 88     {
 89         int y=e[i].po;
 90         if (!e[i].flow) continue;
 91         if (!v[y]) dfs(y);
 92     }
 93 }
 94 
 95 int main()
 96 {
 97     int cas;
 98     scanf("%d",&cas);
 99     for (int i=0; i<256; i++)
100     {
101         for (int j=0; j<8 ;j++)
102           cl[i]^=(i>>j)&1;
103     }
104     while (cas--)
105     {
106         scanf("%d%d",&ln,&lm);
107         n=1<<ln; m=1<<lm;
108         len=-1; memset(p,255,sizeof(p));
109         memset(ans,0,sizeof(ans));
110         for (int i=1; i<=n; i++) scanf("%d",&b[i]);
111         for (int i=1; i<=n; i++) scanf("%d",&u[i]);
112         for (int i=1; i<=n; i++)
113         {
114             mi[i]=mx[i]=0;
115             w[i][0]=-lim; b[i]++;
116             for (int j=1; j<b[i]; j++)
117             {
118                 scanf("%d",&w[i][j]);
119                 if (w[i][mi[i]]<w[i][j]) mi[i]=j;
120             }
121             for (int j=b[i]; j<=m; j++)
122             {
123                 scanf("%d",&w[i][j]);
124                 if (w[i][mx[i]]<w[i][j]) mx[i]=j;
125             }
126             if (!mi[i]) ans[i]=mx[i];
127         }
128         t=n+1;
129         for (int i=0; i<n; i++)
130             if (cl[i])
131             {
132                 for (int j=0; j<ln; j++)
133                 {
134                     int y=i^(1<<j);
135                     build(i+1,y+1,u[i+1]^u[y+1]);
136                 }
137             }
138         for (int i=1; i<=n; i++)
139             if (cl[i-1])
140             {
141                 build(0,i,w[i][mi[i]]+lim);
142                 build(i,t,w[i][mx[i]]+lim);
143             }
144             else {
145                 build(0,i,w[i][mx[i]]+lim);
146                 build(i,t,w[i][mi[i]]+lim);
147             }
148         sap();
149         memset(v,0,sizeof(v));
150         dfs(0);
151         for (int i=p[0]; i>-1; i=e[i].next)
152         {
153             int x=e[i].po;
154             if (ans[x]) continue;
155             if ((v[x]&&cl[x-1])||(!v[x]&&!cl[x-1])) ans[x]=mi[x];
156             else ans[x]=mx[x];
157         }
158         for (int i=1; i<=n; i++)
159         {
160             printf("%d",ans[i]-1);
161             if (i!=n) printf(" "); else puts("");
162         }
163     }
164 }
View Code

 

posted on 2017-02-08 15:22  acphile  阅读(153)  评论(0编辑  收藏  举报