#网络流,费用流#JZOJ 2429 codevs 1803 洛谷 3980 志愿者招募

题目

这个项目需要N 天才能完成,其中第i 天至少需要Ai 个人。一共有M 类志愿者可以招募。其中第i 类可以从第Si 天工作到第Ti 天,招募费用是每人Ci 元。求最少招募费用


分析

直接讲正解,正解就是如图所解释
在这里插入图片描述
精髓就讲完了,then跑费用流


代码

    #include <cstdio>
    #include <deque>
    #define min(x,y) ((x)<(y))?(x):(y)
    #define rr register
    using namespace std;
    struct node{int y,w,f,next;}e[22011];
    int n,s,t,k=1,dis[1005],ls[1005],ans; bool v[1005];
    inline int in(){
    	rr int ans=0; rr char c=getchar();
    	while (c<48||c>57) c=getchar();
    	while (c>47&&c<58) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
    	return ans;
    }
    inline void add(int x,int y,int w,int f){
    	e[++k]=(node){y,w,f,ls[x]}; ls[x]=k;
    	e[++k]=(node){x,0,-f,ls[y]};ls[y]=k;
    }
    inline bool spfa(){
    	for (rr int i=1;i<=n+3;++i) dis[i]=233333333,v[i]=0;
    	rr deque<int>q; q.push_back(t); dis[t]=0; v[t]=1;
    	while (q.size()){
    		rr int x=q.front();	q.pop_front();
    		for (rr int i=ls[x];i;i=e[i].next)
    		if (e[i^1].w&&dis[e[i].y]>dis[x]-e[i].f){
    			dis[e[i].y]=dis[x]-e[i].f;
    			if (!v[e[i].y]){
    				v[e[i].y]=1;
    				if (q.size()&&dis[e[i].y]<dis[q.front()]) q.push_front(e[i].y); else q.push_back(e[i].y);
    			}
    		}
    		v[x]=0;
    	}
    	return dis[s]<233333333;
    }
    inline int dfs(int x,int now){
    	if (x==t) {v[t]=1; return now;}
    	rr int rest=0,f; v[x]=1;
    	for (rr int i=ls[x];i;i=e[i].next)
    	if (!v[e[i].y]&&e[i].w&&dis[e[i].y]==dis[x]-e[i].f){
    		rest+=(f=dfs(e[i].y,min(e[i].w,now-rest)));
    		if (f) ans+=f*e[i].f,e[i].w-=f,e[i^1].w+=f;
    		if (now==rest) return now;
    	}
    	return rest;
    }
    int main(){
    	n=in(); rr int m=in();
    	add(s=n+3,1,23333333,0); add(n+1,t=n+2,23333333,0);
    	for (rr int i=1;i<=n;++i) add(i,i+1,23333333-in(),0);//多余的人
    	while (m--){
    		rr int x=in(),y=in()+1;
    		add(x,y,23333333,in());
    	}
    	while (spfa()){
    		do{
    			for (rr int i=1;i<=n+3;++i) v[i]=0; dfs(s,1e9);
    		}while (v[t]);
    	}
    	return !printf("%d",ans);
    }

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值