首页 > 代码库 > BZOJ3996[TJOI2015]线性代数
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网络流求最小割求解。
代码:
const inf=100000000; type rec=record s,e,w,flow,next:longint; end; var b,bb,d,q:array[0..2002002] of longint; a:array[-1..2002000] of rec; v:array[0..2002000] of boolean; n,m,i,j,k,l,st,ed,ww,top,tar,ans,x:longint; function min(aa,bb:longint):longint; begin if aa<bb then exit(aa);exit(bb); end; procedure add(st,ed,ww:longint); begin inc(top); a[top].s:=st; a[top].e:=ed; a[top].w:=ww; a[top].next:=b[st]; b[st]:=top; end; function bfs:boolean; var head,tail,x,u:longint; y:rec; begin fillchar(v,sizeof(v),false); tail:=1; head:=0; d[st]:=1; v[st]:=true; q[1]:=st; while head<tail do begin inc(head); x:=q[head]; u:=b[x]; while u>0 do begin y:=a[u]; if(not v[y.e])and(y.flow<y.w)then begin v[y.e]:=true; d[y.e]:=d[x]+1; inc(tail); q[tail]:=y.e; end; u:=y.next; end; end; exit(v[tar]); end; function addflow(p,maxflow:longint):longint; var o:longint; y:rec; begin if(p=tar)or(maxflow=0)then exit(maxflow); addflow:=0; while bb[p]>0 do begin y:=a[bb[p]]; if(d[y.e]=d[p]+1)and(y.flow<y.w)then begin o:=addflow(y.e,min(maxflow,y.w-y.flow)); if o>0 then begin inc(a[bb[p]].flow,o); dec(a[bb[p] xor 1].flow,o); dec(maxflow,o); inc(addflow,o); if maxflow=0 then break; end; end; bb[p]:=y.next; end; end; function network:longint; begin network:=0; while bfs do begin for i:=st to tar do bb[i]:=b[i]; inc(network,addflow(st,inf)); end; end; begin readln(n); st:=0; top:=1; tar:=n; for i:=1 to n do for j:=1 to n do begin read(x); if x>0 then begin inc(tar); add(st,tar,x); add(tar,st,0); add(tar,i,inf); add(i,tar,0); add(tar,j,inf); add(j,tar,0); ans:=ans+x; end; end; inc(tar); for i:=1 to n do begin read(j); add(i,tar,j); add(tar,i,0); end; writeln(ans-network); end.
BZOJ3996[TJOI2015]线性代数
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。