P1251 餐巾计划 (网络流)

题意:餐厅每天会需要用Ri块新的餐巾 用完后也会产生Ri块旧的餐巾

   每天购买新的餐巾单价p元 每天产出的旧餐巾可以送到快洗部花费每张c1元 在i + v1天可以使用

   也可以花费c2元每张送到慢洗部 在i + v2天可以使用 问n天的最小花费

题解:把每天拆点 分为用出去的 和得到的旧餐巾

   s -> 用出去的  表示每天可以买新的

   用出去的-> t 表示每天一定会用Ri张纸巾

   s-> 旧 表示每天一定会产生Ri块旧的纸巾

   特判一下后 旧的按题意可以送去快洗和慢洗 然后今天没用完的旧的 明天也可以用

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;

int n, v1, c1, v2, c2, p;
int cnt, s, t;
int q[2005];
ll mincost, maxflow;

struct node {
    int to, nex, val, cost;
}E[25005];
int head[4005];
int cur[4005];

void addedge(int x, int y, int va, int cos) {
    E[++cnt].to = y; E[cnt].nex = head[x]; head[x] = cnt; E[cnt].val = va; E[cnt].cost = cos;
    E[++cnt].to = x; E[cnt].nex = head[y]; head[y] = cnt; E[cnt].val = 0; E[cnt].cost = -cos;
}

int inque[4005];
int dis[4005];
int vis[4005];
bool spfa() {
    for(int i = 0; i <= (n << 1 | 1); i++) dis[i] = INF, inque[i] = 0, cur[i] = head[i], vis[i] = 0;
    queue<int> que;
    que.push(s);
    dis[s] = 0;
    inque[s] = 1;

    while(!que.empty()) {
        int u = que.front();
        que.pop();
        inque[u] = 0;

        for(int i = head[u]; i; i = E[i].nex) {
            int v = E[i].to;
            if(E[i].val > 0 && dis[v] > dis[u] + E[i].cost) {
                dis[v] = dis[u] + E[i].cost;
                if(!inque[v]) {
                    que.push(v);
                    inque[v] = 1;
                }
            }
        }
    }
    if(dis[t] != INF) return true;
    return false;
}

int dfs(int x, int flow) {
    if(x == t) {
        vis[t] = 1;
        return flow;
    }

    vis[x] = 1;
    int used = 0;
    int rflow = 0;
    for(int i = cur[x]; i; i = E[i].nex) {
        cur[x] = i;
        int v = E[i].to;
        if(E[i].val > 0 && dis[v] == dis[x] + E[i].cost && (!vis[v] || v == t)) {
            if(rflow = dfs(v, min(flow - used, E[i].val))) {
                used += rflow;
                E[i].val -= rflow;
                E[i ^ 1].val += rflow;
                mincost += 1LL * rflow * E[i].cost;
                if(used == flow) break;
            }
        }
    }
    return used;
}

void dinic() {
    while(spfa()) {
        vis[t] = 1;
        while(vis[t]) {
            vis[t] = 0;
            dfs(s, INF);
        }
    }
}

int main() {
    mincost = maxflow = 0;
    cnt = 1;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%d", &q[i]), maxflow += 1LL * q[i];
    s = 0; t = 1;
    scanf("%d%d%d%d%d", &p, &v1, &c1, &v2, &c2);

    for(int i = 1; i <= n; i++) {
        addedge(s, i << 1, q[i], 0);
        addedge(i << 1 | 1, t, q[i], 0);
        addedge(s, i << 1 | 1, INF, p);
        if(i + v1 <= n) addedge(i << 1, (i + v1) << 1 | 1, INF, c1);
        if(i + v2 <= n) addedge(i << 1, (i + v2) << 1 | 1, INF, c2);
        if(i + 1 <= n) addedge(i << 1, (i + 1) << 1, INF, 0);
    }
    dinic();
    printf("%lld\n", mincost);
    return 0;
}

原文地址:https://www.cnblogs.com/lwqq3/p/11159292.html

时间: 2024-10-12 00:20:36

P1251 餐巾计划 (网络流)的相关文章

P1251 餐巾计划问题

\(\color{#0066ff}{题目描述}\) 一个餐厅在相继的 N 天里,每天需用的餐巾数不尽相同.假设第 i 天需要 \(r_i\) 块餐巾( i=1,2,...,N).餐厅可以购买新的餐巾,每块餐巾的费用为 p 分;或者把旧餐巾送到快洗部,洗一块需 m 天,其费用为 f 分;或者送到慢洗部,洗一块需 n 天(\(n>m\)),其费用为 s 分(\(s<f\)). 每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗.但是每天洗好的餐巾和

P1251 餐巾计划问题 (费用流)

题目链接 方法: 重点在建图!!!将一天拆成晚上和早上: 1. 从源点向每一天晚上连一条流量为当天所用餐巾x,费用为0的边: 2. 每一天早上向汇点连一条流量为当天所用餐巾x,费用为0的边: 3. 从每一天晚上向第二天晚上连一条流量为INF,费用为0的边,表示每天晚上可以将脏餐巾留到第二天晚上: 4. 从每一天晚上向这一天+快洗所用天数t1的那一天早上连一条流量为INF,费用为快洗所用钱数的边,表示每天晚上可以送去快洗部,在地i+t1天早上收到餐巾 : 5. 从每一天晚上向这一天+慢洗所用天数t

线性规划与网络流10 餐巾计划问题

算法实现题 8-10 餐巾计划问题(习题 8-21)?问题描述:一个餐厅在相继的 N 天里,每天需用的餐巾数不尽相同.假设第 i 天需要 ri块餐巾(i=1,2,…,N).餐厅可以购买新的餐巾,每块餐巾的费用为 p 分:或者把旧餐巾送到快洗部,洗一块需 m 天,其费用为 f 分:或者送到慢洗部,洗一块需 n 天(n>m),其费用为 s<f 分.每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗.但是每天洗好的餐巾和购买的新餐巾数之和,要满足当天

【网络流24题】餐巾计划(图解)

LOJ 6008[网络流24题]餐巾计划 题解 一张图片说明建图方法: 解说: 这种建图方法完美区分开了"脏餐巾"和"干净餐巾"两种餐巾. 每天一定会有r[i]个脏餐巾,所以源点向每天的"脏餐巾"(图上used)连边,容量r[i],费用是0.另外,前一天的脏餐巾也可以留到下一天再处理,所以每天的used点向下一天的used点连一条边,容量INF,费用是0. 每天会需要r[i]个干净餐巾,所以每天的"干净餐巾"向汇点连边(图上n

【网络流24题】餐巾计划问题(最小费用最大流)

[网络流24题]餐巾计划问题(最小费用最大流) 题面 COGS 洛谷上的数据范围更大,而且要开longlong 题解 餐巾的来源分为两种: ①新买的 ②旧的拿去洗 所以,两种情况分别建图 先考虑第一种 因为新买餐巾没有任何限制,并且随时可以买 所以直接从源点向每一天连边,容量为INF,费用为餐巾的价格 因为流要流出去,所以每个点向汇点连边,容量为每天的用量,费用为0 第二种,旧的拿去洗 首先考虑一下怎么算有多少旧的餐巾 每天用旧的餐巾的数量值一定的,不可能变多 因此从源点向这些点连边,容量为每天

LOJ #6008. 「网络流 24 题」餐巾计划

#6008. 「网络流 24 题」餐巾计划 题目描述 一个餐厅在相继的 n nn 天里,每天需用的餐巾数不尽相同.假设第 i ii 天需要 ri r_ir?i?? 块餐巾.餐厅可以购买新的餐巾,每块餐巾的费用为 P PP 分:或者把旧餐巾送到快洗部,洗一块需 M MM天,其费用为 F FF 分:或者送到慢洗部,洗一块需 N NN 天,其费用为 S SS 分(S<F S < FS<F). 每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗.

餐巾计划问题

餐巾计划问题 Time Limit: 1000 MS  Memory Limit: 65536 KB Description 一个餐厅在相继的N 天里,每天需用的餐巾数不尽相同.假设第i天需要ri块餐巾(i=1, 2,-,N).餐厅可以购买新的餐巾,每块餐巾的费用为p分:或者把旧餐巾送到快洗部, 洗一块需m天,其费用为f 分:或者送到慢洗部,洗一块需n 天(n>m),其费用为s< f 分. 每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多 少块保存起来延期送洗.

【题解】餐巾计划问题

[题解]餐巾计划问题 orz argent 一定要注意不要调到题目里的坑里来了,要记得脱离实际(大雾). 建模方法:我觉得没什么好讲的,真的是灵感问题,此外,这个问题可以直接无源汇上下界网络流.但是我不会 graph LR 净1 --w=r,c=0--> T 净2 --w=r,c=0--> T 净3 --w=r,c=0--> T 净4 --w=r,c=0--> T S --w=r,c=p--> 净1 S --w=r,c=p--> 净2 S --w=r,c=p-->

AC日记——餐巾计划问题 洛谷 P1084

餐巾计划问题 思路: 氧气优化水过: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 4005 #define maxque 1000005 #define INF 0x7fffffff #define ll long long ll n,head[maxn],E[maxque],V[maxque],W[maxque],F[maxque]; ll pi,qt,qc,st,sc,s,t,cnt=1,day[maxn],