1061: [Noi2008]志愿者招募 - BZOJ
Description
申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管。布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者。经过估算,这个项目需要N 天才能完成,其中第i 天至少需要Ai 个人。 布布通过了解得知,一共有M 类志愿者可以招募。其中第i 类可以从第Si 天工作到第Ti 天,招募费用是每人Ci 元。新官上任三把火,为了出色地完成自己的工作,布布希望用尽量少的费用招募足够的志愿者,但这并不是他的特长!于是布布找到了你,希望你帮他设计一种最优的招募方案。
Input
第一行包含两个整数N, M,表示完成项目的天数和可以招募的志愿者的种类。 接下来的一行中包含N 个非负整数,表示每天至少需要的志愿者人数。 接下来的M 行中每行包含三个整数Si, Ti, Ci,含义如上文所述。为了方便起见,我们可以认为每类志愿者的数量都是无限多的。
Output
仅包含一个整数,表示你所设计的最优方案的总费用。
Sample Input
3 3
2 3 4
1 2 2
2 3 5
3 3 2
Sample Output
14
HINT
招募第一类志愿者3名,第三类志愿者4名 30%的数据中,1 ≤ N, M ≤ 10,1 ≤ Ai ≤ 10; 100%的数据中,1 ≤ N ≤ 1000,1 ≤ M ≤ 10000,题目中其他所涉及的数据均 不超过2^31-1。
首先贴上别人的题解https://www.byvoid.com/blog/noi-2008-employee/
首先肯定都知道这个是线性规划,可以用单纯形法做,但是单纯形法好像很少用一样,反正我是不会
既然不会线性规划,我们只好转换成网络流了,因为网络流也是一种线性规划我就不说什么了,弱菜表示完全想不到.....,线性规划转化为网络流,完全不懂啊
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 const 2 maxn=1010; 3 maxm=40010; 4 inf=100000000; 5 var 6 a,flag,dis,f,first:array[0..maxn]of longint; 7 next,last,w,liu:array[0..maxm]of longint; 8 n,m,s,t,tot,time,ans,flow:longint; 9 10 procedure insert(u,v,f,l:longint); 11 begin 12 inc(tot); 13 last[tot]:=v; 14 next[tot]:=first[u]; 15 w[tot]:=f; 16 liu[tot]:=l; 17 first[u]:=tot; 18 inc(tot); 19 last[tot]:=u; 20 next[tot]:=first[v]; 21 w[tot]:=-f; 22 first[v]:=tot; 23 end; 24 25 procedure init; 26 var 27 i,j,x,y,z:longint; 28 begin 29 read(n,m); 30 tot:=1; 31 for i:=1 to n do 32 read(a[i]); 33 for i:=1 to m do 34 begin 35 read(x,y,z); 36 insert(x,y+1,z,inf); 37 end; 38 s:=0; 39 t:=n+2; 40 for i:=1 to n+1 do 41 begin 42 z:=a[i]-a[i-1]; 43 if z>0 then insert(s,i,0,z); 44 if z<0 then insert(i,t,0,-z); 45 if i>0 then insert(i,i-1,0,inf); 46 end; 47 end; 48 49 function dfs(x,flow:longint):longint; 50 var 51 i,d,min:longint; 52 begin 53 if x=t then 54 begin 55 inc(ans,flow*dis[t]); 56 exit(flow); 57 end; 58 i:=first[x]; 59 flag[x]:=time; 60 dfs:=0; 61 while i<>0 do 62 begin 63 d:=dis[x]+w[i]-dis[last[i]]; 64 min:=flow; 65 if min>liu[i] then min:=liu[i]; 66 if (min>0) and (d<f[last[i]]) then f[last[i]]:=d; 67 if (min>0) and (d=0) and (flag[last[i]]<>time) then 68 begin 69 d:=dfs(last[i],min); 70 inc(dfs,d); 71 dec(flow,d); 72 dec(liu[i],d); 73 inc(liu[i xor 1],d); 74 end; 75 if flow=0 then break; 76 i:=next[i]; 77 end; 78 end; 79 80 procedure work; 81 var 82 i,del:longint; 83 begin 84 repeat 85 inc(time); 86 for i:=s to t do 87 f[i]:=inf; 88 inc(flow,dfs(s,inf)); 89 del:=inf; 90 for i:=s to t do 91 if (flag[i]<>time) and (del>f[i]) then del:=f[i]; 92 if del=inf then break; 93 for i:=s to t do 94 if flag[i]<>time then inc(dis[i],del); 95 until false; 96 write(ans); 97 end; 98 99 var 100 q:array[0..maxn]of longint; 101 head,tail:longint; 102 103 procedure spfa; 104 var 105 i:longint; 106 begin 107 inc(time); 108 head:=1; 109 tail:=2; 110 fillchar(dis,sizeof(dis),1); 111 q[1]:=s; 112 dis[s]:=0; 113 while head<>tail do 114 begin 115 i:=first[q[head]]; 116 while i<>0 do 117 begin 118 if (liu[i]>0) and (dis[last[i]]>dis[q[head]]+w[i]) then 119 begin 120 if flag[last[i]]<>time then 121 begin 122 q[tail]:=last[i]; 123 flag[last[i]]:=time; 124 tail:=tail mod maxn+1; 125 end; 126 dis[last[i]]:=dis[q[head]]+w[i]; 127 end; 128 i:=next[i]; 129 end; 130 flag[q[head]]:=time-1; 131 head:=head mod maxn+1; 132 end; 133 end; 134 135 begin 136 init; 137 spfa; 138 work; 139 end.