zoukankan      html  css  js  c++  java
  • BZOJ2406矩阵

    题目描述

    题解

    最大值最小,一眼二分没的说。

    然后考虑建出这么个图,每行看做一个点,每列看做一个点,每个点看做一条连接行与列的边,源点向每行连s-mid__s+mid的边,行与列连L__R的边,列到汇连s-mid__s+mid的边。

    然后判断是否有有源汇可行流。

    建图时要让边权先减去下界!

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define N 209
    #define NN 409
    #define inf 2e9
    using namespace std;
    queue<int>q;
    int tot,head[NN],a[N][N],deep[NN],cur[NN],si[N],sj[N],L,R,n,m,du[NN],ans;
    inline int rd(){
        int x=0;char c=getchar();bool f=0;
        while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        return f?-x:x;
    }
    struct edge{int n,to,l;}e[NN*NN*2];
    inline void add(int u,int v,int l){
        e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].l=l;
        e[++tot].n=head[v];e[tot].to=u;head[v]=tot;e[tot].l=0;
    }
    inline bool bfs(int s,int t){
        memset(deep,0,sizeof(deep));
        memcpy(cur,head,sizeof(head));
        q.push(s);deep[s]=1;
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=head[u];i;i=e[i].n){
                int v=e[i].to;
                if(!deep[v]&&e[i].l){deep[v]=deep[u]+1;q.push(v);}
            }
        } 
        return deep[t];
    }
    int dfs(int u,int t,int l){
        if(u==t||!l)return l;
        int flow=0,f;
        for(int &i=cur[u];i;i=e[i].n){
            int v=e[i].to;
            if(deep[v]==deep[u]+1&&(f=dfs(v,t,min(l,e[i].l)))){
                e[i].l-=f;e[i^1].l+=f;l-=f;flow+=f;
                if(!l)break; 
            } 
        }
        return flow;
    }
    inline bool check(int mid){
        int s=0,t=n+m+1,ss=m+n+2,tt=n+m+3;
        memset(head,0,sizeof(head));tot=1;
        memset(du,0,sizeof(du));
        for(int i=1;i<=n;++i){
            int mi=max(0,si[i]-mid);
            du[s]-=mi;du[i]+=mi;add(s,i,si[i]+mid-mi);
        }
        for(int i=1;i<=m;++i){
            int mi=max(0,sj[i]-mid);
            du[n+i]-=mi;du[t]+=mi;add(i+n,t,sj[i]+mid-mi);
        }
        for(int i=1;i<=n;++i)
          for(int j=1;j<=m;++j){du[i]-=L;du[n+j]+=L;add(i,n+j,R-L);}
        add(t,s,inf);
        for(int i=s;i<=t;++i){
            if(du[i]<0)add(i,tt,-du[i]);
            else add(ss,i,du[i]);
        }
        while(bfs(ss,tt))dfs(ss,tt,inf);
        for(int i=head[ss];i;i=e[i].n)if(e[i].l)return 0;
        for(int i=head[tt];i;i=e[i].n)if(e[i^1].l)return 0;
        return 1;
    }
    int main(){
        n=rd();m=rd();
        for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)a[i][j]=rd(),si[i]+=a[i][j],sj[j]+=a[i][j]; 
        L=rd();R=rd(); 
        int l=0,r=200000;
        while(l<=r){
            int mid=(l+r)>>1;
            if(check(mid))ans=mid,r=mid-1;else l=mid+1;
        }
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    通用分页后台显示
    自定义的JSP标签
    Java反射机制
    Java虚拟机栈---本地方法栈
    XML建模实列
    XML解析与xml和Map集合的互转
    [离散数学]第二次作业
    [线性代数]2016.10.13作业
    [数字逻辑]第二次作业
    [线性代数]2016.9.26作业
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/10217176.html
Copyright © 2011-2022 走看看