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

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.
View Code
posted @ 2017-01-08 19:40  GhoStreach  阅读(264)  评论(0编辑  收藏  举报