BZOJ 2406 二分+有上下界的网络流判定

思路:

求出每行的和  sum_row

每列的和   sum_line

二分最后的答案mid

S->i  流量[sum_row[i]-mid,sum_row[i]+mid]

i->n+j 流量[L,R]

n+j->T 流量 [sum_line[i]-mid,sum_line[i]+mid]

套用有上下界的网络流 判一下就好了..

这是道有上下界网络流的裸题

//By SiriusRen
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=205,M=222222;
int n,m,a[N][N],sum_row[N],sum_line[N],L,R;
struct Dinic{
    int first[N*2],next[M],v[M],w[M],vis[N*2],tot,T,SS,TT,jy,du[N*2],all;
    void Add(int x,int y,int z){w[tot]=z,v[tot]=y,next[tot]=first[x],first[x]=tot++;}
    void add(int x,int y,int z){Add(x,y,z),Add(y,x,0);}
    bool tell(){
        memset(vis,-1,sizeof(vis)),vis[SS]=0;
        queue<int>q;q.push(SS);
        while(!q.empty()){
            int t=q.front();q.pop();
            for(int i=first[t];~i;i=next[i])
                if(vis[v[i]]==-1&&w[i])
                    vis[v[i]]=vis[t]+1,q.push(v[i]);
        }return vis[TT]!=-1;
    }
    int zeng(int x,int y){
        if(x==TT)return y;
        int r=0;
        for(int i=first[x];~i&&y>r;i=next[i])
            if(vis[v[i]]==vis[x]+1&&w[i]){
                int t=zeng(v[i],min(y-r,w[i]));
                w[i]-=t,w[i^1]+=t,r+=t;
            }
        if(!r)vis[x]=-1;
        return r;
    }
    int flow(){
        int ans=0;
        while(tell())while(jy=zeng(SS,0x3f3f3f3f))ans+=jy;
        return ans;
    }
    bool check(int x){
        memset(first,-1,sizeof(first)),
        all=tot=0,T=n+m+1,SS=n+m+2,TT=n+m+3,
        memset(du,0,sizeof(du));
        add(T,0,0x3f3f3f3f);
        for(int i=1;i<=n;i++)add(0,i,2*x),du[i]+=sum_row[i]-x,du[0]-=sum_row[i]-x;
        for(int i=1;i<=m;i++)add(i+n,T,2*x),du[T]+=sum_line[i]-x,du[i+n]-=sum_line[i]-x;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                add(i,j+n,R-L),du[j+n]+=L,du[i]-=L;
        for(int i=0;i<=T;i++){
            if(du[i]>0)add(SS,i,du[i]),all+=du[i];
            else add(i,TT,-du[i]);
        }if(flow()>=all)return 1;
        return 0;
    }
}d;
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
            sum_row[i]+=a[i][j];
            sum_line[j]+=a[i][j];
        }
    scanf("%d%d",&L,&R);
    int l=0,r=200000,ans=0;
    while(l<=r){
        int mid=(l+r)>>1;
        if(d.check(mid))r=mid-1,ans=mid;
        else l=mid+1;
    }printf("%d\n",ans);
}
时间: 2024-11-20 11:54:18

BZOJ 2406 二分+有上下界的网络流判定的相关文章

【BZOJ2406】矩阵 二分+有上下界的可行流

[BZOJ2406]矩阵 Description Input 第一行两个数n.m,表示矩阵的大小. 接下来n行,每行m列,描述矩阵A. 最后一行两个数L,R. Output 第一行,输出最小的答案: Sample Input 2 2 0 1 2 1 0 1 Sample Output 1 HINT 对于100%的数据满足N,M<=200,0<=L<=R<=1000,0<=Aij<=1000 题解:容易想到二分,并且这个和式可以拆成$\sum A_{ij}-\sum B_

【网络流补全计划】Part.Ⅲ有上下界的网络流

本来心情就非常糟糕调月下毛景树把我最后一点写代码的心情调没了 放弃 开始补全网络流. 之前学了普通最大流,那么现在开始补有上下界的网络流. 在普通最大流中,网络里的每一条边都只有流量的上界即边的容量,而引入上下界网络流之后,每个边不但有一个容量,还有一个流量下界. 我们令B(u,v)表示边(u,v)的下界.于是我们可以有表达式: B(u,v)≤f(u,v)≤C(u,v) 有这个式子可以得到 0≤f(u,v)≤C(u,v)?B(u,v) 至此,我们可以将有上下界的网络流分为几种问题来对待,接下来就

有上下界的网络流2-有源汇带上下界网络流ZOJ3229

ZOJ3229题目大意:一个屌丝给m个女神拍照,计划拍照n天,每一天屌丝可以和C个女神拍照,每天拍照数不能超过D张,而且给每个女神i拍照有数量限制[Li,Ri],对于每个女神n天的拍照总和不能少于Gi,如果有解求屌丝最多能拍多少张照,并求每天给对应女神拍多少张照:否则输出-1. 解题思路:        1.增设一源点st,汇点sd,st到第i天连一条上界为Di下界为0的边,每个女神到汇点连一条下界为Gi上界为正无穷的边,对于每一天,当天到第i个女孩连一条[Li,Ri]的边.        2.

BZOJ 2324 (有上下界的)费用流

思路: 先跑一遍Floyd  更新的时候map[i][j]=map[i][k]+map[k][j]  k需要小于i或j 正常建边: 把所有点 拆点-> i,i+n add(x,y,C,E)表示x->y建边 话费为C  容量为E add(S,0,0,k) add(i,j+n,map[i][j],1) add(j+n,j,0,0x3f3f3f3f)->这条边下界为1 add(j,T,0,1) 这个时候我们有两种方法 1.套用有上下界的网络流 2.把add(j+n,j,0,0x3f3f3f3f

有上下界的网络流1-无源汇带上下界网络流SGU194

今天开始啃网络流了.对于求解无源汇带上下界的网络流,我们可以这样建图:建图模型:         以前写的最大流默认的下界为0,而这里的下界却不为0,所以我们要进行再构造让每条边的下界为0,这样做是为了方便处理.对于每根管子有一个上界容量up和一个下界容量low,我们让这根管子的容量下界变为0,上界为up-low.可是这样做了的话流量就不守恒了,为了再次满足流量守恒,即每个节点"入流=出流",我们增设一个超级源点st和一个超级终点sd.我们开设一个数组du[]来记录每个节点的流量情况.

poj_2396 有上下界的网络流

题目大意 一个mxn的矩阵,给出矩阵中每一行的和sh[1,2...m]以及每一列的数字的和目sv[1,2...n],以及矩阵中的一些元素的范围限制,比如a[1][2] > 1, a[2][3] < 4, a[3][3] = 10等等,且要求矩阵中的每个元素值非负.求出,是否存在满足所有给出的限制条件的矩阵,若存在输出. 题目分析 这么多限制条件..开始只能想到暴力解法+剪枝.这他妈得需要多大的脑洞才能无中生有的想到网络流解法? 不过,给出网络流的想法之后发现采用网络流解法确实很合理,很简单(唯

【bzoj2406】矩阵 二分+有上下界可行流

题目描述 输入 第一行两个数n.m,表示矩阵的大小. 接下来n行,每行m列,描述矩阵A. 最后一行两个数L,R. 输出 第一行,输出最小的答案: 样例输入 2 2 0 1 2 1 0 1 样例输出 1 题解 二分+有上下界可行流 题目一眼二分,问题转化为判断是否存在一种填数方式满足行之和的差与列之和的差都不超过mid. 然后原来的和式就可以转化为$|\sum\limits_{i=1}^na_i-\sum\limits_{i=1}^nb_i|\le mid$,即可得到$\sum\limits_{i

ZOJ 2314 Reactor Cooling 带上下界的网络流

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1314 题意: 给n个点,及m根pipe,每根pipe用来流躺液体的,单向的,每时每刻每根pipe流进来的物质要等于流出去的物质,要使得m条pipe组成一个循环体,里面流躺物质. 并且满足每根pipe一定的流量限制,范围为[Li,Ri].即要满足每时刻流进来的不能超过Ri(最大流问题),同时最小不能低于Li. 求的是最大流. 很久之前就看了带上下界的网络流,一直没看懂

SGU 194. Reactor Cooling(无源汇有上下界的网络流)

时间限制:0.5s 空间限制:6M 题意: 显然就是求一个无源汇有上下界的网络流的可行流的问题 Solution: 没什么好说的,直接判定可行流,输出就好了 code /* 无汇源有上下界的网络流 */ #include <iostream> #include <cstring> #define ms(a,b) memset(a,b,sizeof a) using namespace std; const int MAXN = 209; struct node { int u, v