3144: [Hnoi2013]切糕
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 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
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
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 ", minCut()); 179 }
@Author: YouSiki