zoukankan      html  css  js  c++  java
  • BZOJ 3144 [HNOI2013]切糕 (最大流+巧妙的建图)

    题面:洛谷传送门 BZOJ传送门

    最大流神题

    把点权转化为边权,切糕里每个点$(i,j,k)$向$(i,j,k+1)$连一条流量为$v(i,j,k)$的边

    源点$S$向第$1$层的点连边,第$R+1$层的点向$T$连边,流量均为$inf$

    跑最大流,最大流的流量就是答案

    因为每条纵轴都取了最小的$v$,被割掉的边就是最小的$v$所在的边

    然而题目里还有限制,相邻两个纵轴取值的位置相差的距离不能超过$D$

    如何处理这个限制呢?

    每个点$(i,j,k)$向$(x,y,k-D)$连流量为$inf$的边,$(x,y)$是$(i,j)$相邻的纵轴

    假设纵轴$(i,j)$的割点是$(i,j,k)$

    如果$(x,y)$的割点在$(x,y,k-D)$下面,一定会有一条流量从纵轴$(i,j)$流到$(x,y)$里,然后向上流到汇点$T$

    巧妙地解决了距离的限制问题

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define N1 67010
     5 #define M1 400010
     6 #define L1 45
     7 using namespace std;
     8 const int inf=0x3f3f3f3f;
     9  
    10 int gint()
    11 {
    12     int ret=0,fh=1;char c=getchar();
    13     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
    14     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
    15     return ret*fh;
    16 }
    17 struct Edge{
    18 int to[M1<<1],nxt[M1<<1],flow[M1<<1],head[N1],cte;
    19 void ae(int u,int v,int f)
    20 {
    21     cte++; to[cte]=v; nxt[cte]=head[u];
    22     head[u]=cte; flow[cte]=f; 
    23 }
    24 }e;
    25  
    26 int dep[N1],que[M1],cur[N1],n,m,h,D,hd,tl,S,T;
    27 int bfs()
    28 {
    29     int x,j,v;
    30     memset(dep,-1,sizeof(dep)); memcpy(cur,e.head,sizeof(cur));
    31     hd=1,tl=0; que[++tl]=S; dep[S]=0;
    32     while(hd<=tl)
    33     {
    34         x=que[hd++];
    35         for(j=e.head[x];j;j=e.nxt[j])
    36         {
    37             v=e.to[j];
    38             if( dep[v]==-1 && e.flow[j]>0 )
    39             {
    40                 dep[v]=dep[x]+1;
    41                 que[++tl]=v;
    42             }
    43         }
    44     }
    45     return dep[T]!=-1;
    46 }
    47 int dfs(int x,int limit)
    48 {
    49     int j,v,flow,ans=0;
    50     if(!limit||x==T) return limit;
    51     for(j=cur[x];j;j=e.nxt[j])
    52     {
    53         v=e.to[j]; cur[x]=j;
    54         if( dep[v]==dep[x]+1 && (flow=dfs(v,min(limit,e.flow[j]))) )
    55         {
    56             e.flow[j]-=flow; limit-=flow;
    57             e.flow[j^1]+=flow; ans+=flow;
    58             if(!limit) break;
    59         }
    60     }
    61     return ans;
    62 }
    63 int Dinic()
    64 {
    65     int mxflow=0,j,v,ans=0;
    66     while(bfs())
    67         mxflow+=dfs(S,inf);
    68     return mxflow;
    69 }
    70  
    71 int xx[4]={-1,0,1,0},yy[4]={0,1,0,-1};
    72 int v[L1][L1][L1],id[L1][L1][L1];
    73 inline int check(int x,int y){return (x<1||y<1||x>n||y>m)?0:1;}
    74  
    75 int main()
    76 {
    77     scanf("%d%d%d%d",&n,&m,&h,&D);
    78     int i,j,k,x,y,w,p; e.cte=1; S=0; T=n*m*(h+1)+1;
    79     for(k=1;k<=h+1;k++) for(i=1;i<=n;i++) for(j=1;j<=m;j++) id[k][i][j]=(k-1)*n*m+(i-1)*m+j;
    80     for(k=1;k<=h;k++) for(i=1;i<=n;i++) for(j=1;j<=m;j++) 
    81     {
    82         w=v[k][i][j]=gint(), x=id[k][i][j];
    83         e.ae(x,x+n*m,w), e.ae(x+n*m,x,0);
    84         if(k<=D) continue;
    85         //x+=n*m;
    86         for(p=0;p<4;p++)
    87         {
    88             if(!check(i+xx[p],j+yy[p])) continue;
    89             y=id[k-D][i+xx[p]][j+yy[p]];
    90             e.ae(x,y,inf); e.ae(y,x,0);
    91         }
    92     }
    93     for(i=1;i<=n;i++) for(j=1;j<=m;j++) e.ae(S,id[1][i][j],inf), e.ae(id[1][i][j],S,0);
    94     for(i=1;i<=n;i++) for(j=1;j<=m;j++) e.ae(id[h+1][i][j],T,inf), e.ae(T,id[h+1][i][j],0);
    95     printf("%d
    ",Dinic());
    96     return 0;
    97 }
  • 相关阅读:
    学习篇之String()
    js之Math对象
    js之date()对象
    css之描点定位方式
    js详解之作用域-实例
    js精要之构造函数
    js精要之继承
    js精要之模块模式
    js精要之对象属性
    js精要之函数
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10350290.html
Copyright © 2011-2022 走看看