[bzoj1061]志愿者招募

Posted pywbktda

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[bzoj1061]志愿者招募相关的知识,希望对你有一定的参考价值。

将问题反过来考虑,即最多选择多少人(流量最大)使得答案最少(费用最少),很明显是一个费用流的模型
用一条流表示每一天的人数都+1,可以发现即按如下方式建图:1.对于每一种志愿者,li向ri+1连(+oo,ci)的边;2.对于每一天,向前一天连(+oo,0)的边,表示可以多次覆盖;3.源点向1连一条max(ai)的边
但这样会导致答案过大,因为实际上并不需要每一天都被覆盖max(ai)次
仍然反过来考虑,可以理解为我可以不被覆盖max(ai)-ai次,因此i向i+1连一条max(ai)-ai的边即可

技术图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 1005
 4 #define ll long long
 5 struct ji{
 6     int nex,to,cost;
 7     ll len; 
 8 }edge[N*30];
 9 queue<int>q;
10 int E,n,m,x,y,z,head[N],a[N],vis[N],from[N];
11 ll d[N];
12 void add(int x,int y,ll z,int w){
13     edge[E].nex=head[x];
14     edge[E].to=y;
15     edge[E].len=z;
16     edge[E].cost=w;
17     head[x]=E++;
18     if (E&1)add(y,x,0,-w);
19 }
20 bool spfa(){
21     memset(d,0x3f,sizeof(d));
22     memset(vis,0,sizeof(vis));
23     q.push(0);
24     d[0]=0;
25     while (!q.empty()){
26         int k=q.front();
27         q.pop();
28         vis[k]=0;
29         for(int i=head[k];i!=-1;i=edge[i].nex){
30             int v=edge[i].to;
31             if ((edge[i].len)&&(d[v]>d[k]+edge[i].cost)){
32                 d[v]=d[k]+edge[i].cost;
33                 from[v]=i;
34                 if (!vis[v]){
35                     vis[v]=1;
36                     q.push(v);
37                 }
38             }
39         }
40     }
41     return d[n+1]!=d[n+2];
42 }
43 int main(){
44     scanf("%d%d",&n,&m);
45     ll s=0,ans=0;
46     memset(head,-1,sizeof(head));
47     for(int i=1;i<=n;i++){
48         scanf("%d",&a[i]);
49         s+=a[i];
50     }
51     add(0,1,s,0);
52     for(int i=1;i<=n;i++)add(i,i+1,s-a[i],0);
53     for(int i=1;i<=m;i++){
54         scanf("%d%d%d",&x,&y,&z);
55         add(x,y+1,s,z);
56     }
57     while (spfa()){
58         s=1e18;
59         for(int i=n+1;i;i=edge[from[i]^1].to)s=min(s,edge[from[i]].len);
60         ans+=s*d[n+1];
61         for(int i=n+1;i;i=edge[from[i]^1].to){
62             edge[from[i]].len-=s;
63             edge[from[i]^1].len+=s;
64         }
65     }
66     printf("%lld",ans);
67 }
View Code

 

以上是关于[bzoj1061]志愿者招募的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1061-[Noi2008]志愿者招募

bzoj 1061: [Noi2008]志愿者招募

BZOJ 1061: [Noi2008]志愿者招募 [单纯形法]

BZOJ1061:[NOI2008]志愿者招募——题解

BZOJ 1061 志愿者招募

bzoj1061 [Noi2008]志愿者招募