noi 2008 志愿者招募 费用流

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

 

膜拜:gyh神牛

 

  1 #include<iostream>
  2 #include<cmath>
  3 #include<cstring>
  4 #include<cstdio>
  5 using namespace std;
  6 #define MAXN 1100
  7 #define INF 987654321
  8 #define MAXM 50001
  9 int n,m,top=0;
 10 struct node
 11 {
 12     int cost,num,remain;
 13     node *next,*inv;
 14 };
 15 node *edge[MAXN];
 16 int d[MAXN],Q[MAXM],a[MAXN],used[MAXN],father[MAXN];
 17 node *graph[MAXN],memo[MAXM];
 18 void add(int x,int y,int remain,int cost)
 19 {
 20     node *p=&memo[top++],*q=&memo[top++];
 21     p->num=y; p->remain=remain; p->cost=cost; p->next=graph[x]; graph[x]=p;
 22     q->num=x; q->remain=0; q->cost=-cost; q->next=graph[y]; graph[y]=q;
 23     p->inv=q; q->inv=p;
 24 }
 25 void build_graph()
 26 {
 27     int i;
 28     for(i=1;i<=n;i++)
 29     {
 30         if(a[i]>a[i-1])
 31             add(0,i,a[i]-a[i-1],0);
 32         else
 33             add(i,n+1,a[i-1]-a[i],0);
 34     }
 35     for(i=1;i<n;i++)
 36         add(i+1,i,INF,0);
 37 }
 38 bool SPFA()
 39 {
 40     int left,right,u,v;
 41     memset(d,0x3f,sizeof(d));
 42     memset(used,0,sizeof(used));
 43     Q[left=right=1]=0;
 44     used[0]=1;
 45     d[0]=0;
 46     father[0]=-1;
 47     while(left<=right)
 48     {
 49         u=Q[left++];
 50         for(node *p=graph[u];p;p=p->next)
 51         {
 52             v=p->num;
 53             if(p->remain>0&&d[u]+p->cost<d[v])
 54             {
 55                 d[v]=d[u]+p->cost;
 56                 father[v]=u;
 57                 edge[v]=p;
 58                 if(!used[v])
 59                     used[v]=1,Q[++right]=v;
 60             }
 61         }
 62         used[u]=0;
 63     }
 64     return d[n+1]<INF;
 65 }
 66 int extend()
 67 {
 68     int i,delta=INF,res=0;
 69     for(i=n+1;father[i]!=-1;i=father[i])
 70         delta=min(delta,edge[i]->remain);
 71     for(i=n+1;father[i]!=-1;i=father[i])
 72     {
 73         edge[i]->remain-=delta;
 74         edge[i]->inv->remain+=delta;
 75         res+=delta*edge[i]->cost;
 76     }
 77     return res;
 78 }
 79 int solve()
 80 {
 81     int sum=0;
 82     while(SPFA())
 83         sum+=extend();
 84     printf("%d\n",sum);
 85 }
 86 int main()
 87 {
 88     scanf("%d%d",&n,&m);
 89     int i;
 90     int x,y,z;
 91     for(i=1;i<=n;i++)
 92         scanf("%d",a+i);
 93     for(i=1;i<=m;i++)
 94     {
 95         scanf("%d%d%d",&x,&y,&z);
 96         add(x,y+1,INF,z);
 97     }
 98     build_graph();
 99     solve();
100     return 0;
101 }

posted on 2012-07-19 19:39  myoi  阅读(524)  评论(0编辑  收藏  举报

导航