zoukankan      html  css  js  c++  java
  • ●洛谷 1251 餐巾计划问题

    ●题链:

    https://www.luogu.org/problemnew/show/1251

    ●题解:

    一点启示:建图时要考虑到流量问题,即为了方便使用最小费用最大流算法,要把流量最大时为最终目的考虑进建图。
    拆点,每天拆为两个点i, i',表示每天开始和每天结束
    (s,i,ai,P):在第i天最多买ri个餐巾,花费为P;
    (i,t,ai,0):第i天要用ai块餐巾;
    (s,i',ai,0):第i天用剩的ai块旧餐巾;
    (i',i+M,INF,F):第i天的旧餐巾送到快洗部,花费为F;
    (i',i+N,INF,S):第i天的旧餐巾送到慢洗部,花费为S;
    (i,i+1,INF,0):第i天的没用的餐巾可以留到第i+1天去用。

    SPFA费用流:

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define MAXN 2050
    #define INF 0x3f3f3f3f
    using namespace std;
    struct Edge{
    	int to[MAXN*12],cap[MAXN*12],cot[MAXN*12],nxt[MAXN*12],head[MAXN*2],ent;
    	void Init(){
    		ent=2; memset(head,0,sizeof(head));
    	}
    	void Adde(int u,int v,int w,int c){
    		to[ent]=v; cap[ent]=w; cot[ent]=c;
    		nxt[ent]=head[u]; head[u]=ent++;
    		to[ent]=u; cap[ent]=0; cot[ent]=-c;
    		nxt[ent]=head[v]; head[v]=ent++;
    	}
    	int Next(int i,bool type){
    		return type?head[i]:nxt[i];
    	}
    }E;
    int a[MAXN];
    int Day,P,M,F,N,S,SS,TT;
    int idx(int i,int k){
    	return i+Day*k;
    }
    bool spfa(long long &cost){
    	static bool inq[MAXN*2];
    	static int dis[MAXN*2],p[MAXN*2],flow[MAXN*2];
    	memset(dis,0x3f,sizeof(dis));
    	queue<int>q;
    	q.push(SS); inq[SS]=1; dis[SS]=0; flow[SS]=INF;
    	while(!q.empty()){
    		int u=q.front(); q.pop(); inq[u]=0;
    		for(int i=E.Next(u,1);i;i=E.Next(i,0)){
    			int v=E.to[i];
    			if(!E.cap[i]||dis[v]<=dis[u]+E.cot[i]) continue;
    			dis[v]=dis[u]+E.cot[i]; p[v]=i; flow[v]=min(flow[u],E.cap[i]);
    			if(!inq[v]) inq[v]=1,q.push(v);
    		}
    	}
    	if(dis[TT]==INF) return 0;
    	int u=TT; cost+=1ll*flow[TT]*dis[TT];
    	while(u!=SS){
    		E.cap[p[u]]-=flow[TT];
    		E.cap[p[u]^1]+=flow[TT];
    		u=E.to[p[u]^1];
    	}
    	return 1;
    }
    long long Mincost_Maxflow(){
    	long long cost=0;
    	while(spfa(cost));
    	return cost;
    }
    int main()
    {
    	E.Init();	
    	scanf("%d",&Day); SS=2*Day+1; TT=2*Day+2;
    	for(int i=1;i<=Day;i++){
    		scanf("%d",&a[i]);
    		E.Adde(SS,idx(i,1),a[i],0);
    		E.Adde(idx(i,0),TT,a[i],0);
    	}
    	scanf("%d%d%d%d%d",&P,&M,&F,&N,&S);
    	for(int i=1,_i;i<=Day;i++){
    		E.Adde(SS,idx(i,0),a[i],P);
    		_i=i+M; if(_i<=Day) E.Adde(idx(i,1),idx(_i,0),INF,F);
    		_i=i+N; if(_i<=Day) E.Adde(idx(i,1),idx(_i,0),INF,S);
    	}
    	for(int i=1;i<=Day;i++){
    		if(i!=Day) E.Adde(idx(i,0),idx(i+1,0),INF,0);
    	}
    	long long ans=Mincost_Maxflow();
    	printf("%lld",ans);
    	return 0;
    }
    

    ZKW(dinic实现)费用流:

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define MAXN 2050
    #define INF 0x3f3f3f3f
    using namespace std;
    struct Edge{
    	int to[MAXN*12],cap[MAXN*12],cot[MAXN*12],nxt[MAXN*12],head[MAXN*2],ent;
    	void Init(){
    		ent=2; memset(head,0,sizeof(head));
    	}
    	void Adde(int u,int v,int w,int c){
    		to[ent]=v; cap[ent]=w; cot[ent]=c;
    		nxt[ent]=head[u]; head[u]=ent++;
    		to[ent]=u; cap[ent]=0; cot[ent]=-c;
    		nxt[ent]=head[v]; head[v]=ent++;
    	}
    	int Next(int i,bool type){
    		return type?head[i]:nxt[i];
    	}
    }E;
    int a[MAXN],cur[MAXN*2],dis[MAXN*2];
    int Day,P,M,F,N,S,SS,TT;
    int idx(int i,int k){
    	return i+Day*k;
    }
    bool spfa(){
    	static bool inq[MAXN*2];
    	memset(dis,0x3f,sizeof(dis));
    	queue<int>q;
    	q.push(TT); inq[TT]=1; dis[TT]=0;
    	while(!q.empty()){
    		int u=q.front(); q.pop(); inq[u]=0;
    		for(int i=E.Next(u,1);i;i=E.Next(i,0)){
    			int v=E.to[i];
    			if(!E.cap[i^1]||dis[v]<=dis[u]+E.cot[i^1]) continue;
    			dis[v]=dis[u]+E.cot[i^1];
    			if(!inq[v]) inq[v]=1,q.push(v);
    		}
    	}
    	return dis[SS]<INF;
    }
    int dfs(int u,int reflow){
    	if(u==TT||reflow==0) return reflow;
    	int flowout=0,f,d=dis[u]; dis[u]=INF;
    	for(int &i=cur[u];i;i=E.Next(i,0)){
    		int v=E.to[i];
    		if(d!=dis[v]+E.cot[i]||!E.cap[i]) continue;
    		f=dfs(v,min(reflow,E.cap[i]));
    		flowout+=f; E.cap[i^1]+=f;
    		reflow-=f;	E.cap[i]-=f;
    		if(!reflow) break;
    	}
    	return flowout;
    }
    long long ZKW_Mincost(){
    	long long cost=0;
    	while(spfa()){
    		memcpy(cur,E.head,sizeof(E.head));
    		cost+=1ll*dis[SS]*dfs(SS,INF);
    	}
    	return cost;
    }
    int main()
    {
    	E.Init();	
    	scanf("%d",&Day); SS=2*Day+1; TT=2*Day+2;
    	for(int i=1;i<=Day;i++){
    		scanf("%d",&a[i]);
    		E.Adde(SS,idx(i,1),a[i],0);
    		E.Adde(idx(i,0),TT,a[i],0);
    	}
    	scanf("%d%d%d%d%d",&P,&M,&F,&N,&S);
    	for(int i=1,_i;i<=Day;i++){
    		E.Adde(SS,idx(i,0),a[i],P);
    		_i=i+M; if(_i<=Day) E.Adde(idx(i,1),idx(_i,0),INF,F);
    		_i=i+N; if(_i<=Day) E.Adde(idx(i,1),idx(_i,0),INF,S);
    	}
    	for(int i=1;i<=Day;i++){
    		if(i!=Day) E.Adde(idx(i,0),idx(i+1,0),INF,0);
    	}
    	long long ans=ZKW_Mincost();
    	printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    [rabbitmq] python版本(二) 工作队列
    [rabbitmq] python版本(一)HelloWorld
    rabbitmq安装上手
    leetcode1 两数之和
    mybatis学习笔记(一)入门上手
    神经网络简介
    hexo+github pages搭建个人博客
    简单RTSCamera实现
    数据结构复习:树
    LINQ
  • 原文地址:https://www.cnblogs.com/zj75211/p/7930947.html
Copyright © 2011-2022 走看看