BZOJ 3144: [Hnoi2013]切糕

3144: [Hnoi2013]切糕

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1564  Solved: 839
[Submit][Status][Discuss]

Description

Input

第一行是三个正整数P,Q,R,表示切糕的长P、 宽Q、高R。第二行有一个非负整数D,表示光滑性要求。接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x,y,z) (1≤x≤P, 1≤y≤Q, 1≤z≤R)。 
100%的数据满足P,Q,R≤40,0≤D≤R,且给出的所有的不和谐值不超过1000。

Output

仅包含一个整数,表示在合法基础上最小的总不和谐值。

Sample Input

2 2 2
1
6 1
6 1
2 6
2 6

Sample Output

6

HINT

 

最佳切面的f为f(1,1)=f(2,1)=2,f(1,2)=f(2,2)=1

 

Source

 
[Submit][Status][Discuss]

 

OTZ 最小割

 

如果用$(x,y,z)$表示网络中的点,那么有两类边:

  1. $<(x,y,z),(x,y,z+1),V[x][y][z]>$

  2. $<(x,y,z),(x',y',z-D),INF>$

求最小割即可,注意细节。

 

  1 #include <cstdio>
  2 #include <cstring>
  3 
  4 inline char Char(void)
  5 {
  6     static const short siz = 1024;
  7     
  8     static char buf[siz];
  9     static char *hd = buf + siz;
 10     static char *tl = buf + siz;
 11     
 12     if (hd == tl)
 13         fread(hd = buf, 1, siz, stdin);
 14     
 15     return *hd++;
 16 }
 17 
 18 inline int Int(void)
 19 {
 20     int ret = 0, neg = 0, c = Char();
 21     
 22     for (; c < 48; c = Char())
 23         if (c == '-')neg ^= true;
 24     
 25     for (; c > 47; c = Char())
 26         ret = ret * 10 + c - '0';
 27     
 28     return neg ? -ret : ret;
 29 }
 30 
 31 const int mxn = 45;
 32 const int siz = 2000005;
 33 const int inf = 1000000007;
 34 
 35 int s, t;
 36 int hd[siz];
 37 int to[siz];
 38 int fl[siz];
 39 int nt[siz];
 40 
 41 inline void add(int u, int v, int f)
 42 {
 43     static int tot = 0, init = 1;
 44     
 45     if (init)memset(hd, -1, sizeof(hd)), init = 0;
 46     
 47     nt[tot] = hd[u]; to[tot] = v; fl[tot] = f; hd[u] = tot++;
 48     nt[tot] = hd[v]; to[tot] = u; fl[tot] = 0; hd[v] = tot++;
 49 }
 50 
 51 int dep[siz];
 52 
 53 inline bool bfs(void)
 54 {
 55     static int que[siz], head, tail;
 56     memset(dep, 0, sizeof(dep));
 57     head = 0, tail = 0;
 58     que[tail++] = s;
 59     dep[s] = 1;
 60     
 61     while (head != tail)
 62     {
 63         int u = que[head++], v; 
 64         
 65         for (int i = hd[u]; ~i; i = nt[i])
 66             if (!dep[v = to[i]] && fl[i])
 67                 dep[que[tail++] = v] = dep[u] + 1;
 68     }
 69     
 70     return dep[t];
 71 }
 72 
 73 int cur[siz];
 74 
 75 inline int min(int a, int b)
 76 {
 77     return a < b ? a : b;
 78 }
 79 
 80 int dfs(int u, int f)
 81 {
 82     if (u == t || !f)
 83         return f;
 84     
 85     int used = 0, flow, v;
 86     
 87     for (int i = hd[u]; ~i; i = nt[i])
 88         if (fl[i] && dep[v = to[i]] == dep[u] + 1)
 89         {
 90             flow = dfs(v, min(fl[i], f - used));
 91             
 92             used += flow;
 93             fl[i] -= flow;
 94             fl[i^1] += flow;
 95             
 96             if (fl[i])
 97                 cur[u] = i;
 98             
 99             if (used == f)
100                 return f;
101         }
102         
103     if (!used)
104         dep[u] = 0;
105         
106     return used;
107 }
108 
109 inline int minCut(void)
110 {
111     int maxFlow = 0, newFlow;
112     
113     while (bfs())
114     {
115         memcpy(cur, hd, sizeof(cur));
116             
117         while (newFlow = dfs(s, inf))
118             maxFlow += newFlow;
119     }
120     
121     return maxFlow;
122 }
123 
124 int P, Q, R, D, V[mxn][mxn][mxn];
125 
126 inline int pos(int i, int j, int k)
127 {
128     if (k < 1)return s;
129     
130     return (i - 1) * (Q * R) + (j - 1) * R + k;
131 }
132 
133 const int mv[4][2] = 
134 {
135     {0, +1},
136     {0, -1},
137     {-1, 0},
138     {+1, 0}
139 };
140 
141 signed main(void)
142 {
143     P = Int();
144     Q = Int();
145     R = Int();
146     D = Int();
147     
148     for (int k = 1; k <= R; ++k)
149         for (int i = 1; i <= P; ++i)
150             for (int j = 1; j <= Q; ++j)
151                 V[i][j][k] = Int();
152                 
153     s = 0, t = P * Q * R + 1;
154     
155     for (int i = 1; i <= P; ++i)
156         for (int j = 1; j <= Q; ++j)
157         {
158             for (int k = 1; k <= R; ++k)
159             {
160                 add(pos(i, j, k - 1), pos(i, j, k), V[i][j][k]);
161                 
162                 for (int l = 0; l < 4; ++l)
163                 {
164                     int x = i + mv[l][0];
165                     int y = j + mv[l][1];
166                     
167                     if (x < 1 || x > P)continue;
168                     if (y < 1 || y > Q)continue;
169                     
170                     if (k - D > 0)
171                         add(pos(i, j, k), pos(x, y, k - D), inf);
172                 }
173             }
174             
175             add(pos(i, j, R), t, inf);
176         }
177             
178     printf("%d\n", minCut());
179 }

 

@Author: YouSiki

 

posted @ 2017-01-12 08:58  YouSiki  阅读(245)  评论(0编辑  收藏  举报