bzoj2406: 矩阵

来源:互联网 发布:mac不能复制文件到u盘 编辑:程序博客网 时间:2024/06/03 11:24

直接求不好求想到网络流模型,对每行每列算和,二分答案,对每行建点xi,每列建点yi,从s到xi连[sum-mid,sum+mid]边,对每列yi到t连[sum-mid,sum+mid]边,代表行的点和代表列的点连[L,R]的边,跑上下界可行流(注释部分为求方案)。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;queue<int> q;const int inf=0x7f7f7f7f;int read(){    char ch=getchar();int f=0;    while(ch<'0'||ch>'9')ch=getchar();    while(ch>='0'&&ch<='9'){f=(f<<1)+(f<<3)+ch-'0';ch=getchar();}    return f;}int a[205][205],n,m,h[505],l[505],L,R,ans[505][505],s,t,ss,tt,temp,cur[505];struct node{    int from;    int to;    int next;    int w;}edge[500005];int head[505],tot,dis[505];void add(int u,int v,int w){    edge[tot].from=u;    edge[tot].to=v;    edge[tot].next=head[u];    edge[tot].w=w;    head[u]=tot++;}void ins(int u,int v,int low,int high){    if(low>0)    {        add(ss,v,low);        add(v,ss,0);        add(u,tt,low);        add(tt,u,0);        add(u,v,high-low);        add(v,u,0);    }    else    {        add(u,v,high);        add(v,u,0);    }}bool bfs(){    q.push(ss);    memset(dis,-1,sizeof(dis));    dis[ss]=0;    while(!q.empty())    {        int x=q.front();        q.pop();        for(int i=head[x];i!=-1;i=edge[i].next)        {            if(edge[i].w&&dis[edge[i].to]==-1)            {                dis[edge[i].to]=dis[x]+1;                q.push(edge[i].to);            }        }    }    if(dis[tt]==-1)    return 0;    return 1;}int dfs(int x,int flow){    if(x==tt||!flow)    {        return flow;    }    int ret=0;    for(int i=cur[x];i!=-1;i=edge[i].next)    {        if(dis[edge[i].to]==dis[x]+1)        {            int f=dfs(edge[i].to,min(flow,edge[i].w));            edge[i].w-=f;edge[i^1].w+=f;            if(edge[i].w)            cur[x]=i;            ret+=f;flow-=f;            if(!flow) break;        }    }    if(!ret)    dis[x]=-1;    return ret;}void dinic(){    temp=0;    while(bfs())    {        for(int i=0;i<=n+m+10;i++)        cur[i]=head[i];        temp+=dfs(ss,0x7f7f7f7f);    }}bool check(int mid){    tot=0;    memset(head,-1,sizeof(head));    for(int i=1;i<=n;i++)    {        ins(s,i,h[i]-mid,h[i]+mid);    }    for(int i=1;i<=m;i++)    {        ins(i+n,t,l[i]-mid,l[i]+mid);    }    for(int i=1;i<=n;i++)    {        for(int j=1;j<=m;j++)        {            ins(i,j+n,L,R);        }    }    ins(t,s,0,0x7f7f7f7f);    dinic();    for(int i=0;i<tot;i++)    {        if((edge[i].from==ss||edge[i].to==tt)&&edge[i].w)        return 0;        if((edge[i].from>=1&&edge[i].from<=n&&edge[i].to>=n+1&&edge[i].to<=n+m))        ans[edge[i].from][edge[i].to]=L+edge[i].w;    }    return 1;}int find(){    int left=0,right=2000000,mid,an=2000000;    while(left<=right)    {        mid=left+right>>1;        if(check(mid))        {            an=mid,right=mid-1;        }        else left=mid+1;    }    return an;}int main(){    n=read(),m=read();    s=n+m+1,t=s+1,ss=t+1,tt=ss+1;    for(int i=1;i<=n;i++)    {        for(int j=1;j<=m;j++)        {            a[i][j]=read();            h[i]+=a[i][j];            l[j]+=a[i][j];        }    }    L=read(),R=read();    int minans=find();    cout<<minans<<endl;    for(int i=0;i<tot;i++)    {        if((edge[i].to>=1&&edge[i].to<=n&&edge[i].from>=n+1&&edge[i].from<=n+m))        ans[edge[i].to][edge[i].from-n]=L+edge[i].w;    }    /*for(int i=1;i<=n;i++)    {        for(int j=1;j<=m;j++)        {            printf("%d ",ans[i][j]);        }        printf("\n");    }*/}
原创粉丝点击