Description
Input
Output
仅包含一个整数,表示可以获得的最大能源收入。注意,你也可以选择不进行任何攻击,这样能源收入为0。
Sample Input
3 2
10 0
20 0
-10 0
-5 1 0 0
100 1 2 1
100 0
Sample Output
25
HINT
在样例中, 植物P1,1可以攻击位置(0,0), P2, 0可以攻击位置(2,1)。
一个方案为,首先进攻P1,1, P0,1,此时可以攻击P0,0 。共得到能源收益为(-5)+20+10 = 25。注意, 位置(2,1)被植物P2,0保护,所以无法攻击第2行中的任何植物。
【大致数据规模】
约20%的数据满足1 ≤ N, M ≤ 5;
约40%的数据满足1 ≤ N, M ≤ 10;
约100%的数据满足1 ≤ N ≤ 20,1 ≤ M ≤ 30,-10000 ≤ Score ≤ 10000 。
详情请见胡伯涛《最小割模型在信息学竞赛中的应用》中最大权闭合图
但是有一点不同,因为有些点不能取,所以我们首先拓扑一下,把有用的点选出来,然后再跑最小割
1 const 2 maxn=22; 3 maxm=33; 4 inf=10000000; 5 var 6 d,a,first,q:array[0..maxn*maxm]of longint; 7 next,last:array[0..maxn*maxm*maxn*maxm]of longint; 8 map:array[0..maxn*maxm,0..maxn*maxm]of longint; 9 n,m,tot,sum,cnt:longint; 10 11 function calc(i,j:longint):longint; 12 begin 13 exit(i*m+j+1); 14 end; 15 16 procedure insert(x,y:longint); 17 begin 18 inc(tot); 19 last[tot]:=y; 20 next[tot]:=first[x]; 21 first[x]:=tot; 22 inc(d[y]); 23 end; 24 25 procedure init; 26 var 27 i,j,k,l,r,x,y:longint; 28 begin 29 read(n,m); 30 for i:=0 to n-1 do 31 for j:=0 to m-1 do 32 begin 33 read(a[calc(i,j)]); 34 read(k); 35 if j>0 then insert(calc(i,j),calc(i,j-1)); 36 for l:=1 to k do 37 begin 38 read(x,y); 39 insert(calc(i,j),calc(x,y)); 40 end; 41 end; 42 l:=1;r:=0; 43 for i:=0 to n -1do 44 if d[calc(i,m-1)]=0 then 45 begin 46 inc(r); 47 q[r]:=calc(i,m-1); 48 end; 49 while l<=r do 50 begin 51 if a[q[l]]>0 then inc(sum,a[q[l]]); 52 if a[q[l]]>0 then inc(map[0,q[l]],a[q[l]]); 53 if a[q[l]]<0 then inc(map[q[l],n*m+1],-a[q[l]]); 54 i:=first[q[l]]; 55 while i<>0 do 56 begin 57 dec(d[last[i]]);inc(map[last[i],q[l]],inf); 58 if d[last[i]]=0 then 59 begin 60 inc(r); 61 q[r]:=last[i]; 62 end; 63 i:=next[i]; 64 end; 65 inc(l); 66 end; 67 cnt:=r; 68 end; 69 70 var 71 dis,vh,his,pre:array[0..maxn*maxm]of longint; 72 flow:longint; 73 74 procedure sap; 75 var 76 i,j,aug,min:longint; 77 flag:boolean; 78 begin 79 vh[0]:=cnt+2; 80 i:=0;aug:=inf; 81 while dis[i]<n*m+2 do 82 begin 83 his[i]:=aug; 84 flag:=false; 85 for j:=0 to n*m+1 do 86 if (map[i,j]>0) and (dis[i]=dis[j]+1) then 87 begin 88 flag:=true; 89 if aug>map[i,j] then aug:=map[i,j]; 90 pre[j]:=i; 91 i:=j; 92 if i=n*m+1 then 93 begin 94 inc(flow,aug); 95 while i<>0 do 96 begin 97 inc(map[i,pre[i]],aug); 98 dec(map[pre[i],i],aug); 99 i:=pre[i]; 100 end; 101 aug:=inf; 102 end; 103 break; 104 end; 105 if flag then continue; 106 min:=n*m+1; 107 for j:=0 to n*m+1 do 108 if (map[i,j]>0) and (dis[j]<min) then min:=dis[j]; 109 dec(vh[dis[i]]); 110 if vh[dis[i]]=0 then break; 111 dis[i]:=min+1; 112 inc(vh[min+1]); 113 if i<>0 then 114 begin 115 i:=pre[i]; 116 aug:=his[i]; 117 end; 118 end; 119 writeln(sum-flow); 120 end; 121 122 begin 123 init; 124 sap; 125 end.