zoukankan      html  css  js  c++  java
  • Codeforces Gym 101190 NEERC 16 .D Delight for a Cat (上下界的费用流)

    ls是一个特别堕落的小朋友,对于n个连续的小时,他将要么睡觉要么打隔膜,一个小时内他不能既睡觉也打隔膜
    ,因此一个小时内他只能选择睡觉或者打隔膜,当然他也必须选择睡觉或打隔膜,对于每一个小时,他选择睡觉或
    打隔膜的愉悦值是不同的,对于第i个小时,睡觉的愉悦值为si,打隔膜的愉悦值为ei,同时又有一个奥妙重重的
    规定:对于任意一段连续的k小时,ls必须至少有t1时间在睡觉,t2时间在打隔膜。那么ls想让他获得的愉悦值尽
    量大,他该如何选择呢?

    题意:就是N天,每天可以选择S或者E,每一天S或者E有自己的收益,求最大收益,且满足每个连续K天,只是有Ms天选择了S,Me天选择了E。

    输出最大收益,以及对应的方案。

    思路:和上一题有点像,不过加了下界,问题不大,直接去看题解就好了。

    只需要把相邻的边容量改为最大-最小即可,费用为,表示最多流出去mx-mn这么多,留在这里的流量保证了下界。 对于输出方案,只需要看对应的流是否饱和即可。

    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 1010
    using namespace std;
    int To[maxn*6],Laxt[maxn],Next[maxn*6],cap[maxn*6],cost[maxn*6],tag[maxn];
    int S,T,cnt=1;  ll dis[maxn],ans;//建边的时候注意开对应大小的空间 
    bool inq[maxn],vis[maxn];
    deque<int>q;
    void add(int u,int v,int c,int cc)
    { Next[++cnt]=Laxt[u];Laxt[u]=cnt;To[cnt]=v;cap[cnt]=c;cost[cnt]=cc; }
    bool spfa()
    {
        for(int i=0;i<=T;i++) inq[i]=0;
        for(int i=0;i<=T;i++) dis[i]=1LL<<60; //这样更新,必须保证T的编号最大 
        inq[T]=1; dis[T]=0; q.push_back(T);
        while(!q.empty())
        {    
            int u=q.front(); q.pop_front();
            inq[u]=0;
            for(int i=Laxt[u];i;i=Next[i])
            {
                int v=To[i];
                if(cap[i^1]&&dis[v]>dis[u]-cost[i])
                {
                    dis[v]=dis[u]-cost[i];
                    if(!inq[u]){
                        inq[v]=1;
                        if(q.empty()||dis[v]>dis[q.front()]) q.push_back(v);
                        else q.push_front(v);
                    }
                }
            }
        }
        return dis[S]<(1LL<<60);
    }
    int dfs(int u,int flow)
    {
        vis[u]=1;
        if(u==T||flow==0) return flow;
        int tmp,delta=0;
        for(int i=Laxt[u];i;i=Next[i])
        {
            int v=To[i];
            if((!vis[v])&&cap[i]&&dis[v]==dis[u]-cost[i])
            {
                tmp=dfs(v,min(cap[i],flow-delta));
                delta+=tmp; cap[i]-=tmp; cap[i^1]+=tmp;
            }
        }
        return delta;
    }
    int s[maxn],e[maxn];
    int main()
    {
        int N,K,mn,mx,i;
        scanf("%d%d%d%d",&N,&K,&mx,&mn);
        for(i=1;i<=N;i++) scanf("%d",&s[i]),ans+=s[i];
        for(i=1;i<=N;i++) scanf("%d",&e[i]),e[i]-=s[i];
        mx=K-mx; S=0; T=N+2; int SS=N+1;
        add(S,SS,mx,0); add(SS,S,0,0);
        for(i=1;i<=K;i++){ //先约定前面K个数,先选。 
            add(SS,i,mx,0); add(i,SS,0,0);
        }
        for(i=1;i<=N;i++) add(i,i+1>N?T:i+1,mx-mn,0),add(i+1>N?T:i+1,i,0,0);
        for(i=1;i<=N;i++) add(i,i+K>N?T:i+K,1,-e[i]),tag[i]=cnt,add(i+K>N?T:i+K,i,0,e[i]);
        while(spfa()){
            vis[T]=1;
            while(vis[T]){
                for(i=0;i<=T;i++) vis[i]=0;
                int tmp=dfs(S,mx);
                ans-=(ll)tmp*dis[S];
            }
        }
        printf("%I64d
    ",ans);
        for(i=1;i<=N;i++) 
           if(cap[tag[i]]) putchar('S');
           else putchar('E');
        return 0;
    }
  • 相关阅读:
    常见HTTP状态码(200、301、302、500等)解说
    HTTP协议详解(真的很经典)
    计算机网络基础知识总结
    js调试中打印语句
    关于函数return的一些理解与小实例
    网站的导航菜单 远择一个栏目跳转后,为导航菜单的这个栏目增加选中的样式的思路
    alias记录
    利用vue-cli配合vue-router搭建一个完整的spa流程
    node+vue-cli+webpack搭建教程
    nodejs参考文章
  • 原文地址:https://www.cnblogs.com/hua-dong/p/9392290.html
Copyright © 2011-2022 走看看