• bzoj 2406 矩阵——有源汇上下界可行流


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2406

    二分答案。把 b 的 n 个行作为一排, m 个列作为一排,每行和每列之间连上下界为 L , R 的边,源点向每行连以 “ a 的该行的值的和” 加/减 mid 为上下界的边,每列向汇点连以 “ a 的该列的值的和” 加/减 mid 为上下界的边;然后跑可行流就行了。

    自己把和超级源点及超级汇点的无关的边先连好了,到时候改一改容量就行了。但别忘了把 hd[ ] , cap[ ] , xnt , tp[ ] 都赋回原来的值。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=205,M=N*N<<1,INF=4e7+5;
    int n,m,yhd[N<<1],hd[N<<1],xnt=1,cur[N<<1],bj,to[M],nxt[M],ycap[M],cap[M],dy[N<<1];
    int sh[N],sl[N],s,t,ss,tt,tp[N<<1],ttp[N<<1];
    int dfn[N<<1],q[N<<1],he,tl;
    int Mn(int a,int b){return a<b?a:b;}
    int Mx(int a,int b){return a>b?a:b;}
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    void add(int x,int y,int z)
    {
      to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;cap[xnt]=z;
      to[++xnt]=x;nxt[xnt]=hd[y];hd[y]=xnt;cap[xnt]=0;
    }
    bool bfs(int mid)
    {
      memset(dfn,0,sizeof dfn);dfn[ss]=1;
      q[he=tl=1]=ss;
      while(he<=tl)
        {
          int k=q[he++];
          for(int i=hd[k],v;i;i=nxt[i])
        if(!dfn[v=to[i]]&&cap[i])
          dfn[v]=dfn[k]+1,q[++tl]=v;
        }
      return dfn[tt];
    }
    int dinic(int cr,int flow)
    {
      if(cr==tt)return flow;
      int use=0;
      for(int& i=cur[cr],v;i;i=nxt[i])
        if(dfn[v=to[i]]==dfn[cr]+1&&cap[i])
          {
        int tmp=dinic(v,Mn(flow-use,cap[i]));
        if(!tmp)dfn[v]=0;
        use+=tmp;cap[i]-=tmp;cap[i^1]+=tmp;
        if(use==flow)return use;
          }
      return use;
    }
    bool chk(int mid)
    {
      xnt=bj;memcpy(ttp,tp,sizeof tp);
      memcpy(hd,yhd,sizeof yhd);//
      for(int i=2;i<=bj;i++)cap[i]=ycap[i];///
      for(int i=1;i<=n;i++)
        {
          int l=Mx(sh[i]-mid,0),r=sh[i]+mid;
          cap[dy[i]]=r-l;cap[dy[i]^1]=0;
          ttp[i]+=l;ttp[s]-=l;
        }
      for(int i=1;i<=m;i++)
        {
          int l=Mx(sl[i]-mid,0),r=sl[i]+mid;
          cap[dy[i+n]]=r-l;cap[dy[i+n]^1]=0;
          ttp[i+n]-=l;ttp[t]+=l;
        }
      int val=0;
      for(int i=0;i<=t;i++)
        if(ttp[i]>0)add(ss,i,ttp[i]),val+=ttp[i];
        else if(ttp[i]<0)add(i,tt,-ttp[i]);
      while(bfs(mid))
        memcpy(cur,hd,sizeof hd),val-=dinic(ss,INF);
      return !val;
    }
    int main()
    {
      n=rdn();m=rdn();
      for(int i=1,d;i<=n;i++)
        for(int j=1;j<=m;j++)
          d=rdn(),sh[i]+=d,sl[j]+=d;
      int L=rdn(),R=rdn();
      s=0;t=n+m+1; ss=n+m+2;tt=n+m+3;
      for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
          add(i,j+n,R-L),tp[i]-=L,tp[j+n]+=L;
      add(t,s,INF);
      for(int i=1;i<=n;i++)
        add(s,i,0),dy[i]=xnt-1;
      for(int i=n+1,j=n+m;i<=j;i++)
        add(i,t,0),dy[i]=xnt-1;
      bj=xnt;
      memcpy(yhd,hd,sizeof hd);
      for(int i=2;i<=bj;i++)ycap[i]=cap[i];
      int l=0,r=2e5+5,ans;
      while(l<=r)
        {
          int mid=l+r>>1;
          if(chk(mid))ans=mid,r=mid-1;
          else l=mid+1;
        }
      printf("%d
    ",ans);
      return 0;
    }
  • 相关阅读:
    mysql批量插入数据的基类
    mount命令解析
    常用linux命令记录
    转载一篇大神的博客文章
    linux查看网卡状态
    centos7配置网卡绑定
    coentos7安装python3
    阿里云ecs 硬盘在线扩容
    centos7安装redis5
    centos7 rpm安装nginx
  • 原文地址:https://www.cnblogs.com/Narh/p/10122036.html
Copyright © 2020-2023  润新知