BZOJ3996:[TJOI2015]线性代数
Description
给出一个N*N的矩阵B和一个1*N的矩阵C。求出一个1*N的01矩阵A.使得
D=(A*B-C)*A^T最大。其中A^T为A的转置。输出D
Input
第一行输入一个整数N,接下来N行输入B矩阵,第i行第J个数字代表Bij.
接下来一行输入N个整数,代表矩阵C。矩阵B和矩阵C中每个数字都是不超过1000的非负整数。
Output
输出最大的D
Sample Input
3
1 2 1
3 1 0
1 2 3
2 3 7
1 2 1
3 1 0
1 2 3
2 3 7
Sample Output
2
HINT
1<=N<=500
题解:
这题包装得可真好啊……
D=A*B*A^T-C*A^T
假如A的第i项为1,则D会减去C[1,i]。
假如A的第i项、第j项都为1,则D会加上B[i,j]。
这样,题目就变成了类似于BZOJ1497[NOI2006]最大获利的模型:n个物品,取某个物品会有代价,若同时取某两个物品则会有收益。
题目变成了最大权闭合子图问题,用DINIC网络流求最小割求解。
代码:
1 const 2 inf=100000000; 3 type 4 rec=record 5 s,e,w,flow,next:longint; 6 end; 7 var 8 b,bb,d,q:array[0..2002002] of longint; 9 a:array[-1..2002000] of rec; 10 v:array[0..2002000] of boolean; 11 n,m,i,j,k,l,st,ed,ww,top,tar,ans,x:longint; 12 function min(aa,bb:longint):longint; 13 begin 14 if aa<bb then exit(aa);exit(bb); 15 end; 16 procedure add(st,ed,ww:longint); 17 begin 18 inc(top); 19 a[top].s:=st; 20 a[top].e:=ed; 21 a[top].w:=ww; 22 a[top].next:=b[st]; 23 b[st]:=top; 24 end; 25 function bfs:boolean; 26 var head,tail,x,u:longint; 27 y:rec; 28 begin 29 fillchar(v,sizeof(v),false); 30 tail:=1; head:=0; d[st]:=1; 31 v[st]:=true; q[1]:=st; 32 while head<tail do 33 begin 34 inc(head); x:=q[head]; 35 u:=b[x]; 36 while u>0 do 37 begin 38 y:=a[u]; 39 if(not v[y.e])and(y.flow<y.w)then 40 begin 41 v[y.e]:=true; 42 d[y.e]:=d[x]+1; 43 inc(tail); q[tail]:=y.e; 44 end; 45 u:=y.next; 46 end; 47 end; 48 exit(v[tar]); 49 end; 50 function addflow(p,maxflow:longint):longint; 51 var 52 o:longint; 53 y:rec; 54 begin 55 if(p=tar)or(maxflow=0)then exit(maxflow); 56 addflow:=0; 57 while bb[p]>0 do 58 begin 59 y:=a[bb[p]]; 60 if(d[y.e]=d[p]+1)and(y.flow<y.w)then 61 begin 62 o:=addflow(y.e,min(maxflow,y.w-y.flow)); 63 if o>0 then 64 begin 65 inc(a[bb[p]].flow,o); 66 dec(a[bb[p] xor 1].flow,o); 67 dec(maxflow,o); 68 inc(addflow,o); 69 if maxflow=0 then break; 70 end; 71 end; 72 bb[p]:=y.next; 73 end; 74 end; 75 function network:longint; 76 begin 77 network:=0; 78 while bfs do 79 begin 80 for i:=st to tar do bb[i]:=b[i]; 81 inc(network,addflow(st,inf)); 82 end; 83 end; 84 begin 85 readln(n); st:=0; 86 top:=1; tar:=n; 87 for i:=1 to n do 88 for j:=1 to n do 89 begin 90 read(x); 91 if x>0 then 92 begin 93 inc(tar); 94 add(st,tar,x); 95 add(tar,st,0); 96 add(tar,i,inf); 97 add(i,tar,0); 98 add(tar,j,inf); 99 add(j,tar,0); 100 ans:=ans+x; 101 end; 102 end; 103 inc(tar); 104 for i:=1 to n do 105 begin 106 read(j); 107 add(i,tar,j); 108 add(tar,i,0); 109 end; 110 writeln(ans-network); 111 end.