首页 > 其他 > 详细

【BZOJ 1061】 1061: [Noi2008]志愿者招募 (线性规划与网络流)**

时间:2017-02-25 11:45:29      阅读:217      评论:0      收藏:0      [点我收藏+]

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。

Source

 

 

【分析】

  表示初看觉得这题很经典但是仔细想想发现我不会ORZ。。

  表示不会单纯形法搞线性规划【要学么?

  之前做的网络流24题都没有涉及到线性规划的转化的。。

  这道的确是经典题,但是转化挺难的。。

  推荐博客!!https://www.byvoid.com/zhs/blog/noi-2008-employee#more-916

 

技术分享
  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 using namespace std;
  8 #define Maxn 1010
  9 #define Maxm 10010
 10 #define INF 0xfffffff
 11 
 12 int mymin(int x,int y) {return x<y?x:y;}
 13 
 14 int n,m;
 15 
 16 struct node
 17 {
 18     int x,y,f,c,o,next;
 19 }t[4*Maxm];
 20 int first[Maxn],len;
 21 
 22 void ins(int x,int y,int f,int c)
 23 {
 24     t[++len].x=x;t[len].y=y;t[len].f=f;t[len].c=c;t[len].o=len+1;
 25     t[len].next=first[x];first[x]=len;
 26     t[++len].x=y;t[len].y=x;t[len].f=0;t[len].c=-c;t[len].o=len-1;
 27     t[len].next=first[y];first[y]=len;
 28 }
 29 
 30 int nd[Maxn];
 31 int dis[Maxn],flow[Maxn],pre[Maxn],st,ed;
 32 bool inq[Maxn];
 33 queue<int > q;
 34 
 35 void bfs()
 36 {
 37     while(!q.empty()) q.pop();
 38     // memset(dis,-1,sizeof(dis));
 39     for(int i=1;i<=ed;i++) dis[i]=INF;
 40     memset(inq,0,sizeof(inq));
 41     dis[st]=0;inq[st]=1;q.push(st);
 42     flow[st]=INF;
 43     while(!q.empty())
 44     {
 45         int x=q.front();
 46         for(int i=first[x];i;i=t[i].next) if(t[i].f>0)
 47         {
 48             int y=t[i].y;
 49             if(dis[y]>dis[x]+t[i].c)
 50             {
 51                 dis[y]=dis[x]+t[i].c;
 52                 pre[y]=i;
 53                 flow[y]=mymin(flow[x],t[i].f);
 54                 if(!inq[y])
 55                 {
 56                     q.push(y);
 57                     inq[y]=1;
 58                 }
 59             }
 60         }
 61         q.pop();inq[x]=0;
 62     }
 63 }
 64 
 65 void max_flow()
 66 {
 67     int sum=0;
 68     while(1)
 69     {
 70         bfs();
 71         if(dis[ed]==INF) break;
 72         sum+=dis[ed]*flow[ed];
 73         int x=ed;
 74         while(x!=st)
 75         {
 76             t[pre[x]].f-=flow[ed];
 77             t[t[pre[x]].o].f+=flow[ed];
 78             x=t[pre[x]].x;
 79         }
 80     }
 81     printf("%d\n",sum);
 82 }
 83 
 84 void output()
 85 {
 86     for(int i=1;i<=len;i+=2)
 87     {
 88         printf("%d -> %d = %d , %d \n",t[i].x,t[i].y,t[i].f,t[i].c);
 89     }
 90 }
 91 
 92 int main()
 93 {
 94     scanf("%d%d",&n,&m);
 95     len=0;
 96     for(int i=1;i<=n;i++) scanf("%d",&nd[i]);
 97     memset(first,0,sizeof(first));
 98     for(int i=1;i<=m;i++)
 99     {
100         int l,r,c;
101         scanf("%d%d%d",&l,&r,&c);
102         ins(l,r+1,INF,c);
103     }
104     for(int i=1;i<=n;i++) ins(i+1,i,INF,0);
105     nd[0]=0;
106     st=n+2;ed=st+1;
107     for(int i=1;i<=n;i++) if(nd[i]-nd[i-1]>0) ins(st,i,nd[i]-nd[i-1],0);
108     else if(nd[i]-nd[i-1]<0) ins(i,ed,nd[i-1]-nd[i],0);
109     ins(n+1,ed,nd[n],0);
110     // output();
111     max_flow();
112     return 0;
113 }
View Code

 

  建图超机智的,我想不到啊!!

 

2017-02-25 10:55:41

【BZOJ 1061】 1061: [Noi2008]志愿者招募 (线性规划与网络流)**

原文:http://www.cnblogs.com/Konjakmoyu/p/6441173.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!