1061: [Noi2008]志愿者招募

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/

首先肯定都知道这个是线性规划,可以用单纯形法做,但是单纯形法好像很少用一样,反正我是不会

既然不会线性规划,我们只好转换成网络流了,因为网络流也是一种线性规划我就不说什么了,弱菜表示完全想不到.....,线性规划转化为网络流,完全不懂啊

  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.
View Code
原文地址:https://www.cnblogs.com/Randolph87/p/3662732.html