zoukankan      html  css  js  c++  java
  • 【NOI2008】志愿者招募

    P1588 - 【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。

    Source

    NOI,数学 ,网络流 ,线性规划

    每个时间像下一个时间连一条容量为inf-这个时间需要的人,费用为0。
    S向
    1连容量为INF,费用为0。
    N向T连容量为INF,费用为0。
    然后对于每个人,时间段为
    xy,费用为z,从xy+1连一条容量为inf,费用为z的边。
    然后跑最小费用最大流。
    证明:(其实是瞎掰,欢迎大佬指出错误)
    因为时间段之间连了inf-x的边,就相当于这条边控制了x的流量不能从这里流过,所以只能从那条有费用的边流过去。
    把每个减了
    x的边想像成一个坑,这个坑需要用志愿者来填满。最大流肯定能把这个坑填满,所以求出最小费用最大流就可以了。
     1 #include<set>
     2 #include<map>
     3 #include<queue>
     4 #include<stack>
     5 #include<ctime>
     6 #include<cmath>
     7 #include<string>
     8 #include<vector>
     9 #include<cstdio>
    10 #include<cstdlib>
    11 #include<cstring>
    12 #include<iostream>
    13 #include<algorithm>
    14 #define inf 1999999999
    15 using namespace std;
    16 struct data{
    17   int nex,to,w,c;
    18 }e[30010];
    19 int head[1010],edge=-1,vis[1010],dis[1010],pre[1010];
    20 void add(int from,int to,int w,int c){
    21   e[++edge].nex=head[from];
    22   e[edge].to=to;
    23   e[edge].w=w;
    24   e[edge].c=c;
    25   head[from]=edge;
    26 }
    27 inline bool SPFA(int s,int t){
    28   queue<int>q;
    29   q.push(s);
    30   memset(vis,0,sizeof(vis));
    31   memset(dis,127,sizeof(dis));
    32   int zd=dis[0];
    33   vis[s]=1;dis[s]=0;
    34   while(!q.empty()){
    35     int u=q.front();q.pop();
    36     vis[u]=0;
    37     for(int i=head[u];i!=-1;i=e[i].nex)
    38       if(e[i].w>0 && dis[e[i].to]>dis[u]+e[i].c){
    39     dis[e[i].to]=dis[u]+e[i].c;
    40     pre[e[i].to]=i;
    41     if(!vis[e[i].to])vis[e[i].to]=1,q.push(e[i].to);
    42       }
    43   }
    44   if(dis[t]==zd) return 0;
    45   else return 1;
    46 }
    47 inline int end(int s,int t){
    48   int p,sum=inf,ans=0;
    49   for(int u=t;u!=s;u=e[p^1].to)
    50     p=pre[u],sum=min(sum,e[p].w);
    51   for(int u=t;u!=s;u=e[p^1].to){
    52     p=pre[u];
    53     e[p].w-=sum;
    54     e[p^1].w+=sum;
    55     ans+=sum*e[p].c;
    56   }
    57   return ans;
    58 }
    59 void solve(int s,int t){
    60   int flow=0;
    61   while(SPFA(s,t)) flow+=end(s,t);
    62   printf("%d",flow);
    63 }
    64 int main()
    65 {
    66   freopen("!.in","r",stdin);
    67   freopen("!.out","w",stdout);
    68   int n,m,x,y,z;
    69   memset(head,-1,sizeof(head));
    70   scanf("%d%d",&n,&m);
    71   int s=0,t=n+1;
    72   add(s,1,inf,0),add(1,s,0,0);
    73   for(int i=1;i<=n;i++)
    74     scanf("%d",&x),add(i,i+1,inf-x,0),add(i+1,i,0,0);
    75   for(int i=1;i<=m;i++){
    76     scanf("%d%d%d",&x,&y,&z);
    77     add(x,y+1,inf,z),add(y+1,x,0,-z);
    78   }
    79   solve(s,t);
    80   return 0;
    81 }
    
    
    
     
  • 相关阅读:
    selenium 等待时间
    将博客搬至CSDN
    关于科研和工作的几点思考
    窥探观察者模式
    泛型编程拾遗
    【opencv入门篇】 10个程序快速上手opencv【下】
    【opencv入门篇】 10个程序快速上手opencv【上】
    【opencv入门篇】快速在VS上配置opencv
    【MFC系列】MFC快速设置控件文本字体、大小、颜色、背景
    如何用Qt Creator输出helloworld
  • 原文地址:https://www.cnblogs.com/pantakill/p/6618057.html
Copyright © 2011-2022 走看看