• 【CF802C】 Heidi and Library (hard)(费用流)


    题目链接
    感觉跟餐巾计划问题有点像。费用流。
    决定每天买不买不太好搞,不如先把所有东西都买进来,再卖掉不必要的。
    拆点,每个点拆成(x,y)
    源点向每个点的(x)连费用为当天的价格,流量为1的边。
    每个点的(y)向汇点连费用为0,流量为1的边。
    每个点(x)(y)连流量为1,费用为0的边。
    此时流出的已经等于流入的了,也就是说最大流一定为(n)
    现在考虑加入费用限制。
    每天的(x)向下一天的(x)连流量为(k-1),费用为0的边,表示可以不扔,留到明天,但明天的书还需要一个位置,所以是(k-1)
    每天的前一天向上一个(a_i)出现的位置的(y)连一条费用为(-c_{a_i}),流量为1的边,表示在已经有这本书的情况下,可以卖掉这本书。
    此时求出最小费用即为答案。

    #include <cstdio>
    #include <queue>
    #include <cstring>
    #define INF 2147483647
    using namespace std;
    const int MAXN = 210;
    const int MAXM = 200010;
    queue <int> q; 
    int s, t, now, n;
    struct Edge{
        int from, next, to, rest, cost;
    }e[MAXM];
    int head[MAXN], num = 1, dis[MAXN], vis[MAXN], Flow[MAXN], pre[MAXN];
    inline void Add(int from, int to, int flow, int cost){
        e[++num] = (Edge){ from, head[from], to, flow, cost }; head[from] = num;
        e[++num] = (Edge){ to, head[to], from, 0, -cost }; head[to] = num;
    }
    int RoadsExist(){
        q.push(s);
        memset(dis, 127, sizeof dis);
        dis[s] = 0; Flow[s] = INF; pre[t] = 0;
        while(!q.empty()){
          now = q.front(); q.pop(); vis[now] = 0;
          for(int i = head[now]; i; i = e[i].next)
             if(e[i].rest && dis[e[i].to] > dis[now] + e[i].cost){
               dis[e[i].to] = dis[now] + e[i].cost;
               pre[e[i].to] = i;
               Flow[e[i].to] = min(Flow[now], e[i].rest);
               if(!vis[e[i].to]){
                 vis[e[i].to] = 1;
                 q.push(e[i].to);
               }
             }
        }
        return pre[t];
    }
    int k, maxflow, mincost, sum;
    int a[MAXN], c[MAXN], last[MAXN];
    int main(){
        scanf("%d%d", &n, &k); s = 199; t = 200;
        for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
    	for(int i = 1; i <= n; ++i) scanf("%d", &c[i]);
        for(int i = 1; i <= n; ++i){
           Add(s, i, 1, c[a[i]]);
           if(i != 1) Add(i - 1, i, k - 1, 0);
           Add(i, i + n, 1, 0);
           if(last[a[i]]) Add(i - 1, last[a[i]] + n, 1, -c[a[i]]);
           Add(i + n, t, 1, 0);
           last[a[i]] = i;
        }
        while(RoadsExist()){
          mincost += Flow[t] * dis[t];
          for(int i = t; i != s; i = e[pre[i]].from){
             e[pre[i]].rest -= Flow[t];
             e[pre[i] ^ 1].rest += Flow[t];
          }
        }
        printf("%d
    ", mincost);
        return 0;
    }
    
    
  • 相关阅读:
    【Unity3D】使用MD5值,确保本地Sqlite数据库内容没有被篡改
    《Unity3D》通过对象池模式,管理场景中的元素
    NGUI制作 《九宫格》 图片
    NGUI混合FingerGesture《卷二》分离触摸事件
    js的各种获取大小
    sass基础
    js面向对象开发基础
    正则表达式(进阶篇)
    正则表达式(基础篇)
    jquery源码学习(三)—— jquery.prototype主要属性和方法
  • 原文地址:https://www.cnblogs.com/Qihoo360/p/10514112.html
Copyright © 2020-2023  润新知