zoukankan      html  css  js  c++  java
  • P1251 餐巾计划问题

    题面

    一道特别棒的费用流好题,思路非常巧妙

    对于每一天,我们分为早上和晚上两个节点

    每天早上会消耗(r_i)条干净的毛巾,可以视为流向汇点,所以我们向汇点连一条流量为(r_i),费用为(0​)的边

    每天晚上会产生(r_i)条脏毛巾,可以视为从源点流出,所以我们从源点连一条流量为(r_i),费用为(0)的边

    然后我们考虑以下四种情况:买毛巾,慢洗,快洗,留着攒味

    首先是买毛巾,我们直接让毛巾从源点流向每个早上,所以从源点连一条流量无限大,费用为(p)的边

    然后是慢洗,我们从每个晚上向(n)天之后的早上连一条流量无限大,费用为(s)的边,快洗处理方式类似

    最后是保存,我们直接从每个晚上向下一个晚上连一条流量无限大,费用为(0)的边即可

    以上所建的所有边都需要建对应的反边,这也是费用流的常规写法

    图建好之后,这道题可以说已经做完了,写模板就是了

    下面放代码

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #define ll long long
    #define gc getchar
    #define maxn 4005
    #define maxm 100005
    using namespace std;
    
    inline ll read(){
    	ll a=0;int f=0;char p=gc();
    	while(!isdigit(p)){f|=p=='-';p=gc();}
    	while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=gc();}
    	return f?-a:a;
    }int n,S,T,a,b,c,g,f;ll ans;
    
    struct ahaha{
    	int f,w,to,next;
    }e[maxm<<1];int tot,head[maxn];
    inline void add(int u,int v,int w,int f){
    	e[tot]={f,w,v,head[u]};head[u]=tot++;
    }
    
    deque<int>q;
    int bi[maxn],d[maxn],fl[maxn],la[maxn];
    int spfa(){
    	memset(fl,63,sizeof fl);memset(d,63,sizeof d);
    	memset(bi,0,sizeof bi);d[S]=0;la[T]=-1;q.push_back(S);
    	while(!q.empty()){
    		int u=q.front();q.pop_front();bi[u]=0;
    		for(int i=head[u];~i;i=e[i].next){
    			int v=e[i].to;
    			if(d[v]<=d[u]+e[i].f||e[i].w<=0)continue;
    			d[v]=d[u]+e[i].f;la[v]=i;
    			fl[v]=min(fl[u],e[i].w);
    			if(bi[v])continue;bi[v]=1;
    			if(q.empty()||d[v]<d[q.front()])q.push_front(v);
    			else q.push_back(v);
    		}
    	}return ~la[T];
    }
    
    int main(){memset(head,-1,sizeof head);
    	n=read();S=0;T=n<<1|1;
    	for(int i=1;i<=n;++i){
    		int w=read();
    		add(S,i+n,w,0);add(i+n,S,0,0);
    		add(i,T,w,0);add(T,i,0,0);
    	}
    	for(int i=1;i<n;++i){
    		add(i+n,i+n+1,2147483647,0);
    		add(i+n+1,i+n,0,0);
    	}
    	a=read();b=read();c=read();g=read();f=read();
    	for(int i=1;i<=n;++i){
    		add(S,i,2147483647,a);
    		add(i,S,0,-a);
    	}
    	for(int i=n-b;i;--i){
    		add(i+n,i+b,2147483647,c);
    		add(i+b,i+n,0,-c);
    	}
    	for(int i=n-g;i;--i){
    		add(i+n,i+g,2147483647,f);
    		add(i+g,i+n,0,-f);
    	}
    	while(spfa()){
    		ans+=(ll)fl[T]*d[T];
    		int now=T;
    		while(now!=S){
    			e[la[now]].w-=fl[T];
    			e[la[now]^1].w+=fl[T];
    			now=e[la[now]^1].to;
    		}
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    PHP流程控制考察点
    PHP运算符考察点
    PHP的魔术常量
    android窗体溢出WindowManager$BadTokenException: Unable to add window -- token null is not for an applica
    android网络访问异常java.lang.SecurityException: Permission denied (missing INTERNET permission?)
    快速排序算法思想
    播放Assets下的指定音频时,变成播放所有音频了
    python-01-Python环境搭建
    eclipse安装svn
    DOM children方法
  • 原文地址:https://www.cnblogs.com/hanruyun/p/10433735.html
Copyright © 2011-2022 走看看