zoukankan      html  css  js  c++  java
  • 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
    ", mincost);
        return 0;
    }
    View Code
  • 相关阅读:
    有7g和2g的砝码各一个,怎样称可以3次把140g东西分为50g和90g???????
    中缀到后缀(一个例子)
    动态代理模式的使用
    代理模式用来初始化的延迟下载
    ReentrantLock Condition 实现消费者生产者问题
    Two Sum
    [leetcode]重建二叉树(先序和终须) 中序遍和后续
    (转载)旋转数组查找 最简洁方法 总结
    [不明觉厉] 下一个排列
    codeforces -- 283A
  • 原文地址:https://www.cnblogs.com/lwqq3/p/11159292.html
Copyright © 2011-2022 走看看