bzoj 1061 志愿者招募 有上下界费用流做法

      把每一天看作一个点,每一天的志愿者数目就是流量限制,从i到i+1连边,上下界就是(A[i],+inf)。

      对于每一类志愿者,从T[i]+1到S[i]连边,费用为招募一个志愿者的费用,流量为inf。这样每多1的流量,就多了一个从S[i]到T[i]+1的循环流。

      求一遍无源汇的最小费用可行流就可以了。

      

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<queue>
 6 #define inf 0x3f3f3f3f
 7 #define N 100005
 8 using namespace std;
 9 int n,m;
10 int v[N];
11 int head[N],ver[N],nxt[N],tot,f[N],quan[N];
12 void add(int a,int b,int c,int d)
13 {
14     tot++;nxt[tot]=head[a];head[a]=tot;ver[tot]=b;quan[tot]=d;f[tot]=c;
15     tot++;nxt[tot]=head[b];head[b]=tot;ver[tot]=a;quan[tot]=-d;f[tot]=0;
16     return ;
17 }
18 int S,T;
19 int dis[2005],in[2005],with[2005],mn[2005];
20 bool tell()
21 {
22     memset(dis,0x3f,sizeof(dis));
23     memset(in,0,sizeof(in));
24     dis[S]=0;mn[S]=inf;
25     queue<int>q;
26     q.push(S);
27     while(!q.empty())
28     {
29         int tmp=q.front();q.pop();in[tmp]=0;
30         for(int i=head[tmp];i;i=nxt[i])
31         {
32             if(dis[ver[i]]>dis[tmp]+quan[i]&&f[i])
33             {
34                 dis[ver[i]]=dis[tmp]+quan[i];
35                 with[ver[i]]=i;mn[ver[i]]=min(f[i],mn[tmp]);
36                 if(!in[ver[i]])in[ver[i]]=1,q.push(ver[i]);
37             }
38         }
39     }
40     return dis[T]!=inf;
41 }
42 int zeng()
43 {
44     for(int i=T;i;i=ver[with[i]^1])
45     {
46         f[with[i]]-=mn[T];f[with[i]^1]+=mn[T];
47     }
48     return mn[T]*dis[T];
49 }
50 int main()
51 {
52    scanf("%d%d",&n,&m);
53    S=0;T=n+2;
54    tot=1;
55    int tmp;
56    for(int i=1;i<=n;i++)
57    {
58            scanf("%d",&tmp);
59            add(i,T,tmp,0);
60         add(S,i+1,tmp,0);
61         add(i,i+1,inf,0);
62    }
63    int t1,t2,t3;
64    for(int i=1;i<=m;i++)
65    {
66          scanf("%d%d%d",&t1,&t2,&t3);
67          add(t2+1,t1,inf,t3);
68    }
69    int ans=0;
70    while(tell())ans+=zeng();
71    printf("%d\n",ans);
72    return 0;
73 }

 

      

 

转载于:https://www.cnblogs.com/ezyzy/p/6209869.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值