首先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.