【BZOJ 3144】 [Hnoi2013]切糕

原来dinic没学好啊

 

竟然还有个重要优化!

 

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <cstring>
  4 #include <algorithm>
  5  using  namespace std;
  6  #define MAXN 60
  7  #define INF 10000000
  8  int P,Q,R,D,s,t;
  9  int id[MAXN][MAXN][MAXN],cnt= 0;
 10  int xx[ 5]={ 0, 0, 0, 1,- 1};
 11  int yy[ 5]={ 0, 1,- 1, 0, 0};
 12  int init[MAXN][MAXN][MAXN];
 13  int team[ 1000000],head,tail;
 14  int d[ 100000];
 15  int g[ 1000000],num[ 2000000],nnext[ 2000000],flow[ 2000000],tot= 2;
 16 inline  void Add( int x, int y, int z)
 17 {
 18  //     cout<<x<<' '<<y<<' '<<z<<endl;
 19      nnext[tot]=g[x];
 20     g[x]=tot;
 21     num[tot]=y;
 22     flow[tot]=z;
 23     tot++;
 24     
 25     nnext[tot]=g[y];
 26     g[y]=tot;
 27     num[tot]=x;
 28     flow[tot]= 0;
 29     tot++;
 30 }
 31 inline  bool bfs()
 32 {
 33     head=tail= 0;
 34     memset(d, 0, sizeof(d)); 
 35     team[++tail]=s;d[s]= 1;
 36      while(head<tail)
 37     {
 38          int x=team[++head];
 39          for( int i=g[x];i;i=nnext[i])
 40          if(d[num[i]]== 0&&flow[i]> 0)
 41         {
 42             d[num[i]]=d[x]+ 1;
 43             team[++tail]=num[i];
 44         }
 45     }
 46      if(d[t]== 0return  false;
 47      return  true;
 48 }
 49  int dfs( int x, int mmin)
 50 {
 51      if(x==t)  return mmin;
 52      int tmp,f= 0;
 53      for( int i=g[x];i;i=nnext[i])
 54      if(d[num[i]]==d[x]+ 1&&flow[i]> 0&&(tmp=dfs(num[i],min(mmin,flow[i]))))
 55     {
 56         mmin-=tmp;
 57         f+=tmp;
 58         flow[i]-=tmp;
 59         flow[i^ 1]+=tmp;
 60          if(mmin== 0
 61          return f;
 62     }
 63     
 64     
 65     
 66     
 67     
 68     
 69     
 70     
 71     
 72     
 73     
 74     
 75     
 76      if(f== 0) d[x]= 0;
 77     
 78     
 79     
 80     
 81     
 82     
 83     
 84     
 85     
 86     
 87     
 88     
 89     
 90     
 91      return f;
 92 }
 93  int main()
 94 {
 95      // cin>>P>>Q>>R; 
 96      scanf( " %d %d %d ",&P,&Q,&R); 
 97     //  cin>>D; 
 98      scanf( " %d ",&D);
 99      for( int i= 1;i<=R;i++)
100        for( int j= 1;j<=P;j++)
101           for( int k= 1;k<=Q;k++)
102              id[j][k][i]=++cnt,
103              scanf( " %d ",&init[j][k][i]);
104     s=++cnt;
105     t=++cnt;
106    //   cout<<cnt<<endl;
107       for( int i= 1;i<=P;i++)
108          for( int j= 1;j<=Q;j++)
109         {
110             id[i][j][ 0]=s;
111             id[i][j][R+ 1]=t;
112             init[i][j][R+ 1]=INF;
113              for( int k= 1;k<=R+ 1;k++)
114             {
115                 Add(id[i][j][k- 1],id[i][j][k],init[i][j][k]);
116                  if(k-D>= 1&&k!=R+ 1)
117                      for( int l= 1;l<= 4;l++)
118                          if(i+xx[l]>= 1&&i+xx[l]<=P&&j+yy[l]>= 1&&j+yy[l]<=Q)
119                             Add(id[i][j][k],id[i+xx[l]][j+yy[l]][k-D],INF);         
120             }
121         }
122      int ans= 0;
123      while(bfs()) ans+=dfs(s,INF);
124      // cout<<ans;
125      printf( " %d\n ",ans); 
126      return  0;
127 }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值