BZOJ1061 [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
2 3 4
1 2 2
2 3 5
3 3 2
Sample Output
14
HINT
1 ≤ N ≤ 1000,1 ≤ M ≤ 10000,题目中其他所涉及的数据均 不超过2^31-1。
正解:最小费用最大流
解题报告:完全不知道怎样建图,在网上查了题解,大概是这样,一个点向后一个点连边,容量为inf-a[i],费用为0,然后对于每一个买人的操作,从l到r+1连一个容量为inf,费用为输入费用的边,直接跑最小费用最大流。
1 #include <iostream> 2 #include <iomanip> 3 #include <cstdlib> 4 #include <cstdio> 5 #include <cstring> 6 #include <cmath> 7 #include <string> 8 #include <algorithm> 9 #define int long long 10 #define RG register 11 #define MIN(a,b) a<b?a:b 12 const int N = 100000; 13 const int M = 1000000; 14 const int inf = 914748364121474836; 15 16 using namespace std; 17 18 int head[N],a[N],nxt[N],f[M],vis[N]; 19 int cnt=1,S,T,ans,y=inf,dis[N],fa[N]; 20 21 int gi(){ 22 char ch=getchar();int x=0; 23 while(ch<'0' || ch>'9') ch=getchar(); 24 while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); 25 return x; 26 } 27 28 struct date{ 29 int from,to,val,s; 30 }nn[N]; 31 32 void link(int l,int r,int val,int s){ 33 nn[++cnt]=(date){l,r,val,s},nxt[cnt]=head[l],head[l]=cnt; 34 nn[++cnt]=(date){r,l,0,-s},nxt[cnt]=head[r],head[r]=cnt; 35 return; 36 } 37 38 int spfa(){ 39 for (RG int i=S; i<=T; ++i) dis[i]=inf; 40 int l=0,r=1; 41 f[1]=0,dis[0]=0,vis[0]=1; 42 while(l<r){ 43 ++l; 44 for (RG int i=head[f[l]]; i; i=nxt[i]) 45 if (nn[i].val && dis[f[l]]+nn[i].s<dis[nn[i].to]){ 46 dis[nn[i].to]=dis[f[l]]+nn[i].s; 47 fa[nn[i].to]=i; 48 if (vis[nn[i].to]==0) 49 f[++r]=nn[i].to,vis[nn[i].to]=1; 50 } 51 vis[f[l]]=0; 52 } 53 int gg=inf; 54 for (RG int i=fa[T]; i; i=fa[nn[i].from]) gg=MIN(gg,nn[i].val); 55 gg=MIN(gg,y);y-=gg; 56 ans+=dis[T]*gg; 57 if (y==0) return 0; 58 for (RG int i=fa[T]; i; i=fa[nn[i].from]) nn[i].val-=gg,nn[i^1].val+=gg; 59 return 1; 60 } 61 62 main(){ 63 freopen("x.in","r",stdin); 64 freopen("x.out","w",stdout); 65 int n=gi(),m=gi();T=n+1; 66 for (RG int i=1; i<=n; ++i) a[i]=gi(); 67 link(S,1,inf,0); 68 for (RG int i=1; i<=n; ++i) link(i,i+1,inf-a[i],0); 69 for (RG int i=1; i<=m; ++i){ 70 RG int l=gi(),r=gi(),s=gi(); 71 link(l,r+1,inf,s); 72 } 73 while(spfa()); 74 printf("%lld",ans); 75 return 0; 76 }