• luogu1251 餐巾计划问题


    ss是源点,代表餐巾卖家,tt是汇点,代表记账收钱者。
    记p(i)是i天早晨的可用毛巾数,q(i)是i天完了的废毛巾数。
    建图见注释

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    using namespace std;
    typedef long long ll;
    int n, mmm, nnn, ss, tt, hea[4005], cnt, pre[4005];
    ll r[2005], ppp, fff, sss, minCost, dis[4005];
    const ll oo=0x3f3f3f3f3f3f3f3f;
    bool vis[4005];
    queue<int> d;
    struct Edge{
    	int too, nxt;
    	ll val, cst;
    }edge[25005];
    inline int p(int x){
    	return x;
    }
    inline int q(int x){
    	return x+n;
    }
    void add_edge(int fro, int too, ll val, ll cst){
    	edge[cnt].nxt = hea[fro];
    	edge[cnt].too = too;
    	edge[cnt].val = val;
    	edge[cnt].cst = cst;
    	hea[fro] = cnt++;
    }
    void addEdge(int fro, int too, ll val, ll cst){
    	add_edge(fro, too, val, cst);
    	add_edge(too, fro, 0, -cst);
    }
    bool spfa(){
    	memset(dis, 0x3f, sizeof(dis));
    	memset(pre, -1, sizeof(pre));
    	dis[ss] = 0;
    	d.push(ss);
    	vis[ss] = true;
    	while(!d.empty()){
    		int x=d.front();
    		d.pop();
    		vis[x] = false;
    		for(int i=hea[x]; i!=-1; i=edge[i].nxt){
    			int t=edge[i].too;
    			if(dis[t]>dis[x]+edge[i].cst && edge[i].val>0){
    				dis[t] = dis[x] + edge[i].cst;
    				pre[t] = i;
    				if(!vis[t]){
    					vis[t] = true;
    					d.push(t);
    				}
    			}
    		}
    	}
    	return dis[tt]!=oo;
    }
    void dinic(){
    	while(spfa()){
    		ll tmp=oo;
    		for(int i=pre[tt]; i!=-1; i=pre[edge[i^1].too])
    			tmp = min(tmp, edge[i].val);
    		for(int i=pre[tt]; i!=-1; i=pre[edge[i^1].too]){
    			edge[i].val -= tmp;
    			edge[i^1].val += tmp;
    			minCost += tmp * edge[i].cst;
    		}
    	}
    }
    int main(){
    	memset(hea, -1, sizeof(hea));
    	cin>>n;
    	for(int i=1; i<=n; i++)	scanf("%lld", &r[i]);
    	cin>>ppp>>mmm>>fff>>nnn>>sss;
    	ss = 0; tt = n + n + 1;
    	for(int i=1; i<=n; i++){
    		addEdge(ss, p(i), r[i], ppp);//买毛巾
    		addEdge(ss, q(i), r[i], 0);//每天完了都要用掉这么多毛巾
    		addEdge(p(i), tt, r[i], 0);//对每天的新毛巾记账
    		if(i+mmm<=n)	addEdge(q(i), p(i+mmm), oo, fff);//快洗
    		if(i+nnn<=n)	addEdge(q(i), p(i+nnn), oo, sss);//慢洗
    		if(i<n)	addEdge(q(i), q(i+1), oo, 0);//废毛巾滞留
            //注意没有必要新毛巾滞留,因为刚好有新毛巾总比滞留新毛巾好
    	}
    	dinic();
    	cout<<minCost<<endl;
    	return 0;
    }
    
  • 相关阅读:
    GridView自定义分页
    intro
    ListView和DataPager初试
    在DataGrid中,如何录入数量及单价的时候自动算出金额
    常用正则表达式
    ASP.NET中基类页的设计和使用
    Asp.net实现无刷新检测用户名
    在asp.net2.0中使用存储过程
    .NET中的抽象工厂
    用C#生成随机中文汉字验证码的基本原理 [转]
  • 原文地址:https://www.cnblogs.com/poorpool/p/8110701.html
Copyright © 2020-2023  润新知