zoukankan      html  css  js  c++  java
  • BZOJ1889 : Maximal

    二分答案,判断是否存在合法方案使得每个数都不超过$mid$。

    考虑网络流建图:

    $i$点的流量下限为$max(a_i-mid,0)$,费用为$1$,故拆点进行限制。

    $i$向$i+1$、$S$向$i$、$i$向$T$连边,费用为$0$。

    那么一条增广路径对应选择一个区间进行减$1$。

    求出流量不超过$K$时的最小费用可行流,若有解且费用不超过$M$,则可行。

    #include<cstdio>
    const int N=510,M=100010,inf=~0U>>2;
    int n,K,m,i,a[N],L,R,mx,MID,ans,flow,cost,tmp;
    int u[M],v[M],c[M],co[M],nxt[M],t,S,T,SS,TT,l,r,q[M],g[N],lim[N],f[N],d[N];bool in[N];
    inline void add(int x,int y,int l,int r,int zo){
      lim[x]-=l,lim[y]+=l;cost+=l*zo;
      r-=l;
      if(!r)return;
      u[++t]=x;v[t]=y;c[t]=r;co[t]=zo;nxt[t]=g[x];g[x]=t;
      u[++t]=y;v[t]=x;c[t]=0;co[t]=-zo;nxt[t]=g[y];g[y]=t;
    }
    bool spfa(){
      int x,i;
      for(i=1;i<=TT;i++)d[i]=inf,in[i]=0;
      d[SS]=0;in[SS]=1;l=r=M>>1;q[l]=SS;
      while(l<=r){
        x=q[l++];
        if(x==TT)continue;
        for(i=g[x];i;i=nxt[i])if(c[i]&&co[i]+d[x]<d[v[i]]){
          d[v[i]]=co[i]+d[x];f[v[i]]=i;
          if(!in[v[i]]){
            in[v[i]]=1;
            if(d[v[i]]<d[q[l]])q[--l]=v[i];else q[++r]=v[i];
          }
        }
        in[x]=0;
      }
      return d[TT]<inf;
    }
    bool check(){
      flow=cost=0;
      for(t=i=1;i<=TT;i++)g[i]=lim[i]=0;
      for(i=1;i<=n;i++){
        add(S,i,0,K,0);
        add(i+n,T,0,K,0);
        if(i<n)add(i+n,i+1,0,K,0);
        add(i,i+n,a[i]>MID?a[i]-MID:0,mx,1);
      }
      add(T,S,0,K,0);
      for(i=1;i<=T;i++)if(lim[i]>0)add(SS,i,0,lim[i],0),flow+=lim[i];else add(i,TT,0,-lim[i],0);
      while(spfa()){
        for(tmp=inf,i=TT;i!=SS;i=u[f[i]])if(tmp>c[f[i]])tmp=c[f[i]];
        for(flow-=tmp,cost+=d[i=TT]*tmp;i!=SS;i=u[f[i]])c[f[i]]-=tmp,c[f[i]^1]+=tmp;
      }
      return !flow&&cost<=m;
    }
    int main(){
      scanf("%d%d%d",&n,&K,&m);
      S=n*2+1;T=S+1;SS=T+1;TT=SS+1;
      for(i=1;i<=n;i++){
        scanf("%d",&a[i]);
        if(R<a[i])R=a[i];
      }
      mx=ans=R--;
      while(L<=R){
        MID=(L+R)>>1;
        if(check())R=(ans=MID)-1;else L=MID+1;
      }
      return printf("%d",ans),0;
    }
    

      

  • 相关阅读:
    深入理解ThreadLocal
    JAVA守护线程
    JAVA THREAD.JOIN方法详解
    JAVA中断机制详解
    Socket中的异常和参数设置
    WebSocket实战
    程序里面的system.out.println()输出到其他位置,不输出到tomcat控制台。
    数据库连接未关闭,conn与rs未关闭
    Ajax简单应用-购物车
    1.链表和数组的区别在哪里?
  • 原文地址:https://www.cnblogs.com/clrs97/p/7135617.html
Copyright © 2011-2022 走看看