zoukankan      html  css  js  c++  java
  • 【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-Ai,费用0

      志愿者从SiTi连边,容量INF,费用Ci,用这些边填坑

      虚拟源,汇点STS1,容量INFTn+1,容量INF,费用均为0

      最小费用最大流即可。

      证明{

        源汇点容量为INF,保证最大流为INF

        天数之间的容量上限,故需要志愿者的边填补。

        又根据增广路的性质,可知一定能够满足条件。

        这也是为什么容量为INF-Ai的原因。

      }

    }

        

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<vector>
     6 #include<queue>
     7 #include<ctime>
     8 #include<cmath>
     9 #include<map>
    10 #include<set>
    11 #define MAXX 11003
    12 #define INF 99999999
    13 using namespace std;
    14 struct edge{
    15   int nxt,to,c,w;
    16 }e[MAXX*4];
    17 int head[MAXX],pre[MAXX],dis[MAXX],in[MAXX],n,m,x,cc,tt,ss,ans,tot;
    18 void add(int from,int to,int c,int w){
    19   e[tot].nxt=head[from];
    20   e[tot].to=to;
    21   e[tot].w=w;
    22   e[tot].c=c;
    23   head[from]=tot++;
    24 }
    25 void ADD(int from,int to,int c,int w){
    26   add(from,to,c,w);
    27   add(to,from,0,-w);
    28 }
    29 bool SPFA(int s,int t){
    30   queue<int>que;
    31   while(!que.empty())que.pop();
    32   for(int i=1;i<=n+3;++i)dis[i]=INF,in[i]=false;
    33   que.push(s);in[s]=true;dis[s]=0;
    34   while(!que.empty()){
    35     int u=que.front();
    36     for(int i=head[u];i!=-1;i=e[i].nxt)
    37       if(e[i].c>0&&dis[e[i].to]>dis[u]+e[i].w){
    38     int v=e[i].to;
    39     dis[v]=dis[u]+e[i].w;
    40     pre[v]=i;
    41     if(!in[v])in[v]=true,que.push(v);
    42       }
    43     in[u]=false;
    44     que.pop();
    45     }if(dis[t]==INF)return false;
    46   int u,p,sum=INF;
    47   for(u=t;u!=s;u=e[p^1].to)
    48     p=pre[u],sum=min(sum,e[p].c);
    49   for(u=t;u!=s;u=e[p^1].to){
    50     p=pre[u];
    51     e[p].c-=sum,e[p^1].c+=sum;
    52     ans+=sum*e[p].w;
    53     }return true;
    54 }
    55 int mincostflow(int s,int t){
    56   while(SPFA(s,t));
    57   return ans;
    58 }
    59 int main(){
    60   memset(head,-1,sizeof(head));
    61   scanf("%d%d",&n,&m);
    62   for(int i=1;i<=n;++i)
    63     if(i!=1&&i!=n){
    64       scanf("%d",&x);
    65       ADD(i,i+1,INF-x,0);
    66     }else if(i==1){int x;
    67       scanf("%d",&x);
    68       ADD(0,1,INF,0);
    69       ADD(1,2,INF-x,0);
    70     }else {
    71       scanf("%d",&x);
    72       ADD(n,n+1,INF-x,0);
    73       ADD(n+1,n+2,INF,0);
    74     }
    75   for(int i=1;i<=m;++i){
    76     scanf("%d%d%d",&ss,&tt,&cc);
    77     ADD(ss,tt+1,INF,cc);
    78   }
    79   printf("%d",mincostflow(0,n+2));
    80   return 0;
    81 }

  • 相关阅读:
    MongoDB 聚合函数及排序
    MongoDB 关系运算符及统计个数及跳过分页
    MongoDB 正则表达式查询
    MongoDB 范围查询
    MongoDB 逻辑运算符
    MongoDB数据库
    python 判断文件夹存在,不存在创建文件夹
    MySQL 数据库操作
    MySQL 数据库连接命令
    PyCharm Django 显示一个简单页面
  • 原文地址:https://www.cnblogs.com/zzmmm/p/6658222.html
Copyright © 2011-2022 走看看