zoukankan      html  css  js  c++  java
  • bzoj2400

    首先xor类的题目一定要逐位考虑,因为位位之间是不相互影响的
    逐位考虑每个点是0还是1,这就转化成了一个这样一个问题
    对于每个点可以选择属于S集合(这位是0)或T集合(这位是1)
    某些的点对(一条边的两端)属于不同集合会产生一个附加值1(边权)
    现在要是附加值最小(边权当前位为1的边最少),并且属于S集合的尽可能多(点权当前位为1尽可能少)
    显然第一个问题是一个最小割的问题,对于已经确定这位是什么的点i来说
    是0则连边s-->i 容量inf,是1则连边i-->t容量是inf,因为这些点当前位是确定的
    然后对一条边(u,v),连边u-->v v-->u 容量都是1,最小割就是最小附加值
    这里为什么不用给不确定的点向s,t连边呢?这个我也没有想清楚
    反正直观的感受,当一条路径直接或间接连接着则两点一个确定为0,一个确定为1,
    那么这条路径最少会产生附加值1,一定要被割断,否则这条路径我一定能使它不产生附加值
    下面考虑让属于S的点(这位是0的点)尽可能多
    考虑在残流网络上是不存在增广路的,也就是对于一个未确定点i,如果这个点能属于S
    那么我从s到i给一个流量,这个流量从点i一定不能流向t,否则就会增大边权和
    因此我们只要对于每个未确定的点i在残流网络上顺着剩余容量大于0的边dfs,
    只要到不了t,那么这个点就可以属于S(这位为0),否则不行
    这样就解决了

      1 const inf=100000007;
      2 type node=record
      3        point,next,flow:longint;
      4      end;
      5 
      6 var edge:array[0..800010] of node;
      7     p,cur,d,a,pre,h,numh:array[0..510] of longint;
      8     v:array[0 ..510] of boolean;
      9     x,y:array[0..2010] of longint;
     10     i,j,n,m,k,len,t,b:longint;
     11     ans1,ans2:int64;
     12 
     13 function min(a,b:longint):longint;
     14   begin
     15     if a>b then exit(b) else exit(a);
     16   end;
     17 
     18 procedure add(x,y,f:longint);
     19   begin
     20     inc(len);
     21     edge[len].point:=y;
     22     edge[len].flow:=f;
     23     edge[len].next:=p[x];
     24     p[x]:=len;
     25   end;
     26 
     27 function sap:longint;
     28   var u,i,j,tmp,neck,q:longint;
     29   begin
     30     fillchar(h,sizeof(h),0);
     31     fillchar(numh,sizeof(numh),0);
     32     numh[0]:=t+1;
     33     u:=0;
     34     for i:=0 to t do
     35       cur[i]:=p[i];
     36     neck:=inf;
     37     sap:=0;
     38     while h[0]<t+1 do
     39     begin
     40       d[u]:=neck;
     41       i:=cur[u];
     42       while i<>-1 do
     43       begin
     44         j:=edge[i].point;
     45         if (edge[i].flow>0) and (h[u]=h[j]+1) then
     46         begin
     47           pre[j]:=u;
     48           cur[u]:=i;
     49           neck:=min(neck,edge[i].flow);
     50           u:=j;
     51           if u=t then
     52           begin
     53             sap:=sap+neck;
     54             while u<>0 do
     55             begin
     56               u:=pre[u];
     57               j:=cur[u];
     58               dec(edge[j].flow,neck);
     59               inc(edge[j xor 1].flow,neck);
     60             end;
     61             neck:=inf;
     62           end;
     63           break;
     64         end;
     65         i:=edge[i].next;
     66       end;
     67       if i=-1 then
     68       begin
     69         dec(numh[h[u]]);
     70         if numh[h[u]]=0 then exit;
     71         tmp:=t;
     72         q:=-1;
     73         i:=p[u];
     74         while i<>-1 do
     75         begin
     76           j:=edge[i].point;
     77           if edge[i].flow>0 then
     78             if h[j]<tmp then
     79             begin
     80               tmp:=h[j];
     81               q:=i;
     82             end;
     83           i:=edge[i].next;
     84         end;
     85         h[u]:=tmp+1;
     86         cur[u]:=q;
     87         inc(numh[h[u]]);
     88         if u<>0 then
     89         begin
     90           u:=pre[u];
     91           neck:=d[u];
     92         end;
     93       end;
     94     end;
     95   end;
     96 
     97 function dfs(x:longint):boolean;
     98   var i,y:longint;
     99   begin
    100     v[x]:=true;
    101     if x=t then exit(true);
    102     i:=p[x];
    103     while i<>-1 do
    104     begin
    105       y:=edge[i].point;
    106       if (edge[i].flow>0) and not v[y] then
    107         if dfs(y) then exit(true);
    108       i:=edge[i].next;
    109     end;
    110     exit(false);
    111   end;
    112 
    113 begin
    114   readln(n,m);
    115   b:=0;
    116   for i:=1 to n do
    117   begin
    118     readln(a[i]);
    119     if (a[i]>0) and (trunc(ln(a[i])/ln(2))>b) then
    120       b:=trunc(ln(a[i])/ln(2)); //显然比以确定点的最大位数还大的位直接取0即可
    121     if a[i]>0 then ans2:=ans2+a[i];
    122   end;
    123   for i:=1 to m do
    124     readln(x[i],y[i]);
    125   t:=n+1;
    126   for i:=0 to b do
    127   begin
    128     len:=-1;
    129     fillchar(p,sizeof(p),255);
    130     for j:=1 to n do
    131       if a[j]>=0 then
    132       begin
    133         if a[j] and (1 shl i)=0 then
    134         begin
    135           add(0,j,inf);
    136           add(j,0,0);
    137         end
    138         else begin
    139           add(j,t,inf);
    140           add(t,j,0);
    141         end;
    142       end;
    143     for j:=1 to m do
    144     begin
    145       add(x[j],y[j],1);
    146       add(y[j],x[j],0);
    147       add(y[j],x[j],1);
    148       add(x[j],y[j],0);
    149     end;
    150     ans1:=ans1+int64(sap)*int64(1 shl i);  //1 shl i是这位位权
    151     for j:=1 to n do
    152       if a[j]<0 then
    153       begin
    154         fillchar(v,sizeof(v),false);
    155         if dfs(j) then ans2:=ans2+1 shl i;  //能访问到t则这个点当前位不能为0
    156       end;
    157   end;
    158   writeln(ans1);
    159   writeln(ans2);
    160 end.
    View Code
  • 相关阅读:
    失控
    组织要登信息化这趟高铁要花多少钱买票?
    信息工作的技术(物理)平台
    IT服务系统组成
    传法授业讲缘分
    做好每周工作总结很重要
    编程:对经验世界的析构与建构
    你在哪编程?你的程序原料是什么?
    人的格局与人的底线
    5方与5W
  • 原文地址:https://www.cnblogs.com/phile/p/4473068.html
Copyright © 2011-2022 走看看