zoukankan      html  css  js  c++  java
  • 【洛谷1251】餐巾计划问题(费用流)

    点此看题面

    • 共有(n)天,第(i)天需要(a_i)个餐盘,每天餐盘用完后会变脏,需清洗后才能再次使用。
    • 你每花(p)的代价可以购买一个餐盘,每个餐盘用完后可以花(d1)天、(c1)的代价或是(d2)天、(c2)的代价送去清洗。
    • 求支撑到这(n)天结束的最小代价。
    • (nle2000)

    网络流套路建图

    此题的核心在于每天需要(a_i)个餐盘的条件的处理,而这实际上是相当套路的。

    我们把每天拆成白天和夜晚两个点,然后从第(i)个白天向超级汇连容量(a_i)、代价(0)的边,从超级源向第(i)个夜晚连容量(a_i)、代价(0)的边。由于这张图所有到超级汇的边一定能流满,而当流满的时候也就说明了第(i)个白天能给出(a_i)个干净的盘子。

    剩下的建图就非常简单了,根据题目中给出的条件建四类边:

    • 购买一个盘子,从超级源向第(i)个白天连一条容量(INF)、代价(p)的边。
    • 不洗,直接从第(i)个夜晚向第(i+1)个夜晚连一条容量(INF)、代价(0)的边(因为无需花费,但不能使用)。
    • 快洗,从第(i)个夜晚向第(i+d1)个白天连一条容量(INF)、代价(c1)的边。
    • 慢洗,从第(i)个夜晚向第(i+d2)个白天连一条容量(INF)、代价(c2)的边。

    然后跑一遍费用流就结束了。

    代码:(O(Dinic))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 2000
    #define INF (int)1e9
    #define LL long long
    using namespace std;
    int n,p,d1,c1,d2,c2;
    class MinCostMaxFlow
    {
    	private:
    		#define PS (2*N+2)
    		#define ES (6*N)
    		#define s (2*n+1)
    		#define t (2*n+2)
    		#define E(x) ((((x)-1)^1)+1)
    		int ee,lnk[PS+5];struct edge {int to,nxt,F,C;}e[2*ES+5];
    		int lst[PS+5],IQ[PS+5],F[PS+5];LL C[PS+5];queue<int> q;
    		I bool SPFA()
    		{
    			RI i,k;for(i=1;i<=t;++i) F[i]=INF,C[i]=1e18;q.push(s),C[s]=0;
    			W(!q.empty()) for(i=lnk[k=q.front()],q.pop(),IQ[k]=0;i;i=e[i].nxt)
    			{
    				if(!e[i].F||C[k]+e[i].C>=C[e[i].to]) continue;
    				C[e[i].to]=C[k]+e[lst[e[i].to]=i].C,F[e[i].to]=min(F[k],e[i].F),
    				!IQ[e[i].to]&&(q.push(e[i].to),IQ[e[i].to]=1);
    			}return F[t]^INF;
    		}
    	public:
    		I void Add(CI x,CI y,CI f,CI c)
    		{
    			e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y,e[ee].F=f,e[ee].C=c,
    			e[++ee].nxt=lnk[y],e[lnk[y]=ee].to=x,e[ee].F=0,e[ee].C=-c;
    		}
    		I LL MCMF()
    		{
    			RI x;LL g=0;W(SPFA()) {g+=C[t]*F[t],x=t;
    				W(x^s) e[lst[x]].F-=F[t],e[E(lst[x])].F+=F[t],x=e[E(lst[x])].to;}
    			return g;
    		}
    }D;
    int main()
    {
    	RI i,x;for(scanf("%d",&n),i=1;i<=n;++i) scanf("%d",&x),D.Add(i,t,x,0),D.Add(s,n+i,x,0);//保证每天有a[i]个干净盘子
    	scanf("%d%d%d%d%d",&p,&d1,&c1,&d2,&c2);
    	for(i=1;i<=n;++i) D.Add(s,i,INF,p),i^n&&(D.Add(n+i,n+i+1,INF,0),0),//购买;不洗
    		i+d1<=n&&(D.Add(n+i,i+d1,INF,c1),0),i+d2<=n&&(D.Add(n+i,i+d2,INF,c2),0);//快洗;慢洗
    	return printf("%lld
    ",D.MCMF()),0;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    好文推荐
    高效词频分析
    内网渗透技巧:判断机器真实外网IP的5种方法总结
    禁用substr、substring、mid函数的sql注入脚本
    内网文件传输
    工作
    我是如何逃过所有杀软进行内网端口转发的
    扎克伯格开发的家用AI: Jarvis
    Python初学者之网络爬虫(二)
    Python初学者之网络爬虫
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu1251.html
Copyright © 2011-2022 走看看