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 }