很像最大权闭合子图的题目
s向每个工作连边,流量为收益
每个工序,由工作i向对应机器连边,流量为租用费
每个机器向t连边,流量为购买费
显然跑最小割,ans=总收益-mincut
1 const inf=200000007; 2 type node=record 3 flow,next,point:longint; 4 end; 5 6 var edge:array[0..3000010] of node; 7 pre,p,cur,numh,h,d:array[0..3010] of longint; 8 ans,n,m,j,t,len,a,b,x,y,i:longint; 9 10 function min(a,b:longint):longint; 11 begin 12 if a>b then exit(b) else exit(a); 13 end; 14 15 procedure add(x,y,z:longint); 16 begin 17 inc(len); 18 edge[len].point:=y; 19 edge[len].flow:=z; 20 edge[len].next:=p[x]; 21 p[x]:=len; 22 end; 23 24 function sap:longint; 25 var tmp,u,i,j,q,neck:longint; 26 begin 27 for i:=0 to t do 28 cur[i]:=p[i]; 29 numh[0]:=t+1; 30 neck:=inf; 31 u:=0; 32 sap:=0; 33 while h[0]<t+1 do 34 begin 35 d[u]:=neck; 36 i:=cur[u]; 37 while i<>-1 do 38 begin 39 j:=edge[i].point; 40 if (edge[i].flow>0) and (h[u]=h[j]+1) then 41 begin 42 pre[j]:=u; 43 cur[u]:=i; 44 neck:=min(neck,edge[i].flow); 45 u:=j; 46 if u=t then 47 begin 48 sap:=sap+neck; 49 while u<>0 do 50 begin 51 u:=pre[u]; 52 j:=cur[u]; 53 dec(edge[j].flow,neck); 54 inc(edge[j xor 1].flow,neck); 55 end; 56 neck:=inf; 57 end; 58 break; 59 end; 60 i:=edge[i].next; 61 end; 62 if i=-1 then 63 begin 64 dec(numh[h[u]]); 65 if numh[h[u]]=0 then exit; 66 q:=-1; 67 tmp:=t; 68 i:=p[u]; 69 while i<>-1 do 70 begin 71 j:=edge[i].point; 72 if edge[i].flow>0 then 73 if h[j]<tmp then 74 begin 75 q:=i; 76 tmp:=h[j]; 77 end; 78 i:=edge[i].next; 79 end; 80 h[u]:=tmp+1; 81 inc(numh[h[u]]); 82 cur[u]:=q; 83 if u<>0 then 84 begin 85 u:=pre[u]; 86 neck:=d[u]; 87 end; 88 end; 89 end; 90 end; 91 92 begin 93 len:=-1; 94 fillchar(p,sizeof(p),255); 95 readln(n,m); 96 t:=n+m+1; 97 for i:=1 to n do 98 begin 99 readln(a,b); 100 ans:=ans+a; 101 add(0,i,a); 102 add(i,0,0); 103 for j:=1 to b do 104 begin 105 readln(x,y); 106 add(i,n+x,y); 107 add(n+x,i,0); 108 end; 109 end; 110 for i:=1 to m do 111 begin 112 readln(x); 113 add(n+i,t,x); 114 add(t,n+1,0); 115 end; 116 writeln(ans-sap); 117 end.