zoukankan      html  css  js  c++  java
  • BZOJ 2406 LuoguP4194 矩阵 有上下界可行流

    分析:

      这道题乍一看……卧槽这都什么玩意……

      然后发现给了个A矩阵,要求一个可行的B矩阵,使得矩阵C=A-B的每一行的和的绝对值和每一列的和的绝对值的最大值最小……

      好拗口啊……

      什么最大值最小之类的,考的无非就是二分,我们二分一个答案,之后建图跑网络流。

      因为要判断是否合法,所以我们想到了用有上下界的可行流,在这里我们采用有源汇的有上下界可行流。

      我们把每行建点,第i行为xi,每列建点,第i列为yi,从S点到每行xi代表的点连边,容量为这一行的数值和±mid,从每一列yi代表的点向T点连边,容量为这一列的数值和±mid。(±mid为的是适应绝对值,-mid代表下界,+mid代表上界)

      还要把每一行对应的点xi分别向每一列代表的点yj连边,上下界为L,R,为的是满足B数组的L和R限制,因为在这里,第i行的点到第j列的点连边的流量,表示的就是B矩阵B(i,j)这个位置的值。

      这只是初步建图,我们要跑可行流,还要按要求将图转化,首先T到S连inf边,转化为无源汇上下界可行流。

      然后建出新的S,T点,按照规则将图进行变换。

      二分判定之后最终得出的结果,就是答案。

    代码:

     1 #include<bits/stdc++.h>
     2 #define ms(a,x) memset(a,x,sizeof(a))
     3 using namespace std;
     4 const int N=205,M=200005,inf=0x3f3f3f3f;
     5 struct node{int y,z,nxt;}e[M];int S,T,tot;
     6 int L,R,n,m,a[N][N],sx[N],sy[N],h[N*5];
     7 int d[N*5],q[N*5],t[N*5],md,c=1,ans;
     8 void add(int x,int y,int z){
     9     e[++c]=(node){y,z,h[x]};h[x]=c;
    10     e[++c]=(node){x,0,h[y]};h[y]=c;
    11 } bool bfs(){
    12     int f=1,t=0;ms(d,-1);
    13     q[++t]=S;d[S]=0;
    14     while(f<=t){
    15         int x=q[f++];
    16         for(int i=h[x],y;i;i=e[i].nxt)
    17         if(d[y=e[i].y]==-1&&e[i].z) 
    18         d[y]=d[x]+1,q[++t]=y;
    19     } return (d[T]!=-1);
    20 } int dfs(int x,int f){
    21     if(x==T) return f;int w,tmp=0;
    22     for(int i=h[x],y;i;i=e[i].nxt)
    23     if(d[y=e[i].y]==d[x]+1&&e[i].z){
    24         w=dfs(y,min(e[i].z,f-tmp));
    25         if(!w) d[y]=-1;e[i].z-=w;
    26         e[i^1].z+=w;tmp+=w;
    27         if(tmp==f) return f;
    28     } return tmp;
    29 } void dinic(){
    30     while(bfs()) tot+=dfs(S,inf);
    31 } bool pd(int lim){
    32     ans=tot=0;int ad;c=1;ms(h,0);ms(t,0);
    33     md=n+m+1;S=0;T=md+1;
    34     for(int i=1;i<=n;i++){
    35         int j=max(0,sx[i]-lim);
    36         int k=sx[i]+lim;t[md]-=j;
    37         t[i]+=j;add(md,i,k-j);//构建残量网络 
    38     } for(int i=1;i<=m;i++){
    39         int j=max(0,sy[i]-lim);
    40         int k=sy[i]+lim;t[md]+=j;
    41         t[i+n]-=j;add(i+n,md,k-j);
    42     } for(int i=1;i<=n;i++)
    43     for(int j=1;j<=m;j++){
    44         t[i]-=L;t[j+n]+=L;
    45         add(i,j+n,R-L);
    46     } for(int i=1;i<=md;i++)
    47     if(t[i]){
    48         if(t[i]>0) add(S,i,t[i]),
    49         ans+=t[i];else add(i,T,-t[i]);
    50     } dinic();ans-=tot;return !ans;
    51 } int main(){
    52     scanf("%d%d",&n,&m);
    53     for(int i=1;i<=n;i++)
    54     for(int j=1;j<=m;j++)
    55     scanf("%d",&a[i][j]),
    56     sx[i]+=a[i][j],sy[j]+=a[i][j];
    57     scanf("%d%d",&L,&R);
    58     int l=0,r=2e5,pos;
    59     while(l<=r){
    60         int mid=l+r>>1;
    61         if(pd(mid)) pos=mid,r=mid-1;
    62         else l=mid+1;
    63     } printf("%d
    ",pos);
    64     return 0;
    65 }
    有上下界可行流
  • 相关阅读:
    sql存储过程简单教程
    深入揭示Web 2.0核心技术——混搭
    Struts 2创始人Patrick Lightbody看《精通Struts 2:Web 2.0开发实战 》
    深入全面阐释Struts 2的方方面面
    设计原本如此简单
    掌握ASP.NET技术之捷径
    Struts 2创始人Patrick Lightbody作序推荐
    Struts 2权威著作
    Amazon超级畅销书之《C#与.NET 3.5高级程序设计(第4版)》
    Web开发领域最热门的话题之混搭
  • 原文地址:https://www.cnblogs.com/Alan-Luo/p/10256512.html
Copyright © 2011-2022 走看看