[NOI2008] 志愿者招募[流量平衡]

时间:2023-03-09 19:31:18
[NOI2008] 志愿者招募[流量平衡]

288. [NOI2008] 志愿者招募

★★★★   输入文件:employee.in   输出文件:employee.out   简单对比
时间限制:2 s   内存限制:512 MB

【问题描述】

申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管。布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者。经过估算,这个项目需要N 天才能完成,其中第i 天至少需要Ai 个人。
布布通过了解得知,一共有M 类志愿者可以招募。其中第i 类可以从第Si 天工作到第Ti 天,招募费用是每人Ci 元。新官上任三把火,为了出色地完成自己的工作,布布希望用尽量少的费用招募足够的志愿者,但这并不是他的特长!于是布布找到了你,希望你帮他设计一种最 优的招募方案。

【输入格式】

输入文件的第一行包含两个整数N, M,表示完成项目的天数和可以招募的志愿者的种类。
接下来的一行中包含N 个非负整数,表示每天至少需要的志愿者人数。
接下来的M 行中每行包含三个整数Si, Ti, Ci,含义如上文所述。为了方便起见,我们可以认为每类志愿者的数量都是无限多的。

【输出格式】
输入文件中仅包含一个整数,表示你所设计的最优方案的总费用。

【输入样例】
3 3
2 3 4
1 2 2
2 3 5
3 3 2
【输出样例】
14

【样例说明】
招募3 名第一类志愿者和4 名第三类志愿者。
【数据规模和约定】
30%的数据中,1 ≤ N, M ≤ 10,1 ≤ Ai ≤ 10;
100%的数据中,1 ≤ N ≤ 1000,1 ≤ M ≤ 10000,题目中其他所涉及的数据均
不超过2^31-1。

[NOI2008] 志愿者招募[流量平衡]

[NOI2008] 志愿者招募[流量平衡]

[NOI2008] 志愿者招募[流量平衡]

[NOI2008] 志愿者招募[流量平衡]

#include<cstdio>
#include<cstring>
#include<iostream>
#define EF if(ch==EOF) return x;
using namespace std;
const int N=;
const int M=1e5+;
const int inf=2e9;
struct data{int x,y;}f[N];
struct edge{int v,next,cap,cost;}e[M<<];int tot=,head[N];
int n,m,cnt,ans,S,T,a[N],dis[N],pre[N],q[M];bool vis[N];
inline int read(){
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;EF;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void add(int x,int y,int z,int cost=){
e[++tot].v=y;e[tot].cap=z;e[tot].cost=cost;e[tot].next=head[x];head[x]=tot;
e[++tot].v=x;e[tot].cap=;e[tot].cost=-cost;e[tot].next=head[y];head[y]=tot;
}
bool spfa(){
memset(vis,,sizeof vis);
memset(dis,0x3f,sizeof dis);
unsigned short h=,t=;q[t]=S;dis[S]=;vis[S]=;
while(h!=t){
int x=q[++h];vis[x]=;
for(int i=head[x];i;i=e[i].next){
if(e[i].cap&&dis[e[i].v]>dis[x]+e[i].cost){
dis[e[i].v]=dis[x]+e[i].cost;
pre[e[i].v]=i;
if(!vis[e[i].v]){
vis[e[i].v]=;
q[++t]=e[i].v;
}
}
}
}
return dis[T]<0x3f3f3f3f;
}
int augment(){
int flow=0x3f3f3f3f;
for(int i=T;i!=S;i=e[pre[i]^].v) flow=min(flow,e[pre[i]].cap);
for(int i=T;i!=S;i=e[pre[i]^].v){
e[pre[i]].cap-=flow;
e[pre[i]^].cap+=flow;
}
return dis[T]*flow;
}
void MCMF(){
while(spfa()) ans+=augment();
}
int main(){
freopen("employee.in","r",stdin);
freopen("employee.out","w",stdout);
n=read();m=read();S=;T=n+;
for(int i=;i<=n;i++) a[i]=read();
for(int i=,x,y,z;i<=m;i++){
x=read();y=read();z=read();
add(x,y+,inf,z);
}
for(int i=;i<=n+;i++) add(i,i-,inf);
for(int i=,now;i<=n+;i++){
now=a[i-]-a[i];
if(now>=) add(i,T,now);
else add(S,i,-now);
}
MCMF();
printf("%d",ans);
return ;
}