• bzoj4842: [Neerc2016]Delight for a Cat


    bzoj4842

    这是一道网络流的题(大家都看出来了吧)

     首先我们简化一下题目,选出最关键的部分(就是知道什么和要求什么,还有条件

    我们在这里把睡觉设为0,至少有t0时间在睡觉,把打隔膜设为1,至少t2时间在打隔膜(方便下面描述)

    这样的话就转换成了一个序列问题 ,数列上的点可以选为0或1,第i个位置选0有si的收益,选1有ei的收益,长度为k的序列里至少有t0个0和t1个1。求如何填数才能令这个序列达的收益最大,输出最大收益和填数方案。

    样例就不用解释了吧,大家都懂。

    假设所有点都选了0,操作由赋值0或1改为将哪些0变为1后更优,每一个0变为1后都有ei-si的收益,一个长度为k的区间内至少有t1个1,定为下界L=t1,至多有k-t0个1(至少有t0个0)定为上界U,(是有上下界的网络流的题!!不过正解不是那样)这样变换后可以试操作更简单。

    既然是网络流的,我们考虑怎么建图,一看是一个序列,先把序列上的点依次连接起来S连向1,n连向T,中间的i连向i+1;

    然后步入正题,看看本题应该怎么做,参考一下下图:

    先只考虑有上界的问题

    对于每个点i,我们将它像i+k号点连一条边,表示选了这个点(0改为1),将这一点的流量分走,分向下一个区间,剩下的流量就 -1  表示这个区间内能改的点的个数-1。

    将S流向1 的边流量设定为上界U,这样可以保证每个k区间的流量都<=上界。这样就能控制住每个区间内最多分出去U的流量,就是说最多选上界个点;

    再考虑下界,就是最少选L个1;也就是说要让这个区间内最少流出L的流量,那么剩下的流量最多就只能流U-L了。所以我们把每个区间末尾的那个边的流量定为U-L控制最多剩下多少流量。

    (大家用各种优美姿势感性理解一下)

    还有注意不要全开long long ;

    不开long long会爆int ,全开会超时~~~这个东西卡了我一个小时。。

    至于怎么输出方案,大家胡乱搞一下就好了。

      1 #include<iostream>
      2 #include<queue>
      3 #include<bit/stdc++.h>
      4 using namespace std;
      5 #define LL long long
      6 #define C continue
      7 #define B break
      8 #define MAXN 101000
      9 #define inf 100000007
     10 inline LL read()
     11 {
     12     LL x=0,f=1;
     13     char ch=getchar();
     14     while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
     15     while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
     16     return x*f;
     17 }
     18 int n,k,t0,t1,S,T,lin[MAXN],t=1;
     19 int v[MAXN],pre[MAXN],U,L,id[MAXN],S0;
     20 LL aa,d[MAXN],AKAKAKAK[MAXN],a[MAXN],ans=0,sum;
     21 int incf[MAXN];
     22 struct adge{
     23     int y,ne,c,v;
     24 }e[2*MAXN];
     25 void insert(int xx,int yy,int cc,int vv)
     26 {
     27     e[++t].y=yy;e[t].v=vv;e[t].c=cc;e[t].ne=lin[xx];lin[xx]=t;
     28     e[++t].y=xx;e[t].v=-vv;e[t].c=0;e[t].ne=lin[yy];lin[yy]=t;
     29 }queue<int> q;
     30 bool SP_spfa(int st)
     31 {
     32     while(q.size())q.pop();
     33     memset(d,127,sizeof(d));
     34     aa=d[1];
     35     memset(v,0,sizeof(v));
     36     q.push(st),d[st]=0,v[st]=1;
     37     incf[st]=(1<<30);
     38     while(q.size())
     39     {
     40         int x=q.front();
     41         q.pop();
     42         v[x]=0;
     43         for(int i=lin[x];i;i=e[i].ne)
     44         {
     45             int y=e[i].y;
     46             if(d[y]>d[x]+e[i].v&&e[i].c)
     47             {
     48                 d[y]=d[x]+e[i].v;
     49                 incf[y]=min(incf[x],e[i].c);
     50                 pre[y]=i;
     51                 if(!v[y])
     52                 {
     53                     v[y]=1;
     54                     q.push(y);
     55                 }
     56             }
     57         }
     58     }
     59     if(d[T]==aa)    return 0;
     60     return 1;
     61 }
     62 void Update()
     63 {
     64     int x=T;
     65     while(x!=S)
     66     {
     67         int i=pre[x];
     68         e[i].c-=incf[T];
     69         e[i^1].c+=incf[T];
     70         x=e[i^1].y;
     71     }
     72     ans+=(LL)d[T]*incf[T];
     73 }
     74 int main()
     75 {
     76     //freopen("www.in","r",stdin);
     77     //freopen("www.out","w",stdout);
     78     n=read(),k=read(),t0=read(),t1=read();
     79     for(int i=1;i<=n;++i)    AKAKAKAK[i]=read(),sum+=AKAKAKAK[i];
     80     for(int i=1;i<=n;++i)    a[i]=read()-AKAKAKAK[i];
     81     S=0,T=n+1;U=k-t0;L=t1;S0=n+2;
     82     insert(S,S0,U,0);
     83     for(int i=1;i<=n;++i)
     84     {
     85         /*insert(i,min(i+k,T),1,-a[i]);
     86         if(i<k)        insert(i,i+1,inf,0);
     87         else        insert(i,i+1,U-L,0);*/
     88         if(i<=k)    insert(S0,i,inf,0);
     89         insert(i,min(i+1,T),U-L,0);
     90                 insert(i,min(i+k,T),1,-a[i]);
     91                 id[i]=t;
     92     }
     93     while(SP_spfa(S))Update();
     94     cout<<sum-ans<<endl;
     95     for(int i=1;i<=n;++i) {
     96         if(e[id[i]^1].c)    putchar('S');
     97         else                putchar('E');
     98     }
     99     //cout<<s<<endl;
    100     return 0;
    101 }
    102    
    代码
  • 相关阅读:
    Go语言指针
    程序员 需要掌握得600个英语单词
    Go语言管道
    Go语言容器
    Go语言切片
    Go语言类型转换
    Go语言数组
    LR静态存储/动态存储/指针变量脚本说明
    MQ报错2009/2085解决方法
    Windows性能监控监视器(perfmon使用)
  • 原文地址:https://www.cnblogs.com/cylyz/p/10598022.html
Copyright © 2020-2023  润新知