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
  • 相关阅读:
    257. Binary Tree Paths
    324. Wiggle Sort II
    315. Count of Smaller Numbers After Self
    350. Intersection of Two Arrays II
    295. Find Median from Data Stream
    289. Game of Life
    287. Find the Duplicate Number
    279. Perfect Squares
    384. Shuffle an Array
    E
  • 原文地址:https://www.cnblogs.com/phile/p/4473068.html
Copyright © 2011-2022 走看看