bzoj 1061

来源:互联网 发布:金融数据分析知乎 编辑:程序博客网 时间:2024/06/08 14:04

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

1 ≤ N ≤ 1000,1 ≤ M ≤ 10000,题目中其他所涉及的数据均 不超过2^31-1。


题解:
模仿别人:https://www.byvoid.com/blog/noi-2008-employee/
确实,只有这里有比较详细的解释了
蒟蒻的网络流很垃圾。。于是看了好一会


因为我们知道网络流肯定都是流量平衡的,所以只要最大流量了,那么肯定就能满足所有的等式------也就是能把所有的常数项满足,就满足条件了
但似乎题目也没有无解的数据,要不他的答案就错了(反正无解也没有答案)
贴一下代码(很多都是抄的):
#include<cstdio>#include<cstring>const int N=1005;const int MAX=1<<30;int n,m;int st1,ed1;struct qq{int x,y;int last;int z,z1,other;}s[50005];int num,last[N];int ans=0;int init1 (int x,int y,int z,int z1){num++;s[num].x=x;s[num].y=y;s[num].z=z;s[num].z1=z1;s[num].last=last[x];last[x]=num;return num;}void init (int x,int y,int z,int z1){int num1=init1(x,y,z,z1),num2=init1(y,x,0,-z1);s[num1].other=num2;s[num2].other=num1;return ;}int dis[N],from[N],q[N];bool q1[N];bool SPFA (){memset(dis,127,sizeof(dis));memset(from,-1,sizeof(from));memset(q1,false,sizeof(q1));int st=1,ed=2;dis[st1]=0;from[st1]=-1;q1[st1]=true;q[st]=st1;while (st!=ed){int x=q[st];for (int u=last[x];u!=-1;u=s[u].last){int y=s[u].y;if (s[u].z>0&&dis[x]+s[u].z1<dis[y]){from[y]=u;dis[y]=dis[x]+s[u].z1;if (q1[y]==false){q1[y]=true;q[ed]=y;ed++;if (ed>=N-1) ed=1;}}}q1[x]=false;st++;if (st>=N-1) st=1;}if (from[ed1]!=-1) return true;return false;}int mymin (int x,int y){return x<y?x:y;}void add (){int x=from[ed1];int f=MAX;while (x!=-1){f=mymin(f,s[x].z);x=from[s[x].x];}x=from[ed1];while (x!=-1){ans=ans+f*s[x].z1;s[x].z-=f;s[s[x].other].z+=f;x=from[s[x].x];}}int main(){num=0;memset(last,-1,sizeof(last));st1=1003;ed1=st1+1;int l=0;scanf("%d%d",&n,&m);for (int u=1;u<=n;u++){int x,a;scanf("%d",&a);x=a-l;l=a;if (x>0) init(st1,u,x,0);else init(u,ed1,-x,0);//常数 init(u+1,u,MAX,0);//Y值}init(n+1,ed1,l,0);for (int u=1;u<=m;u++){int x,y,z;scanf("%d%d%d",&x,&y,&z);init(x,y+1,MAX,z);//X值}while (SPFA()==true) add();printf("%d\n",ans);return 0;}
做完这题,我知道了:可以根据流量平衡来进行网络流的建图,以后还有多多练习网络流
0 0
原创粉丝点击