BZOJ3144 [Hnoi2013]切糕

Orz 黄学长好腻害!

首先题目就是要求在一个P*Q的格子里填数,不同的数代价不同,要求相邻的格子差小于D,求最小代价。

最小割模型,我们把一个格子拆成R个点

(x, y, z)向(x, y, z + 1)连边,边权f(x, y, z + 1)

(x, y, z)向(x + dx, y + dy, z - d)连边,边权inf

然后割一下就好了,正确性嘛。。。应该是对的。。。

  1 /**************************************************************
  2     Problem: 3144
  3     User: rausen
  4     Language: C++
  5     Result: Accepted
  6     Time:596 ms
  7     Memory:14056 kb
  8 ****************************************************************/
  9  
 10 #include <cstdio>
 11 #include <cstring>
 12 #include <algorithm>
 13  
 14 using namespace std;
 15 const int N = 100005;
 16 const int M = N * 10;
 17 const int inf = 1e9;
 18 const int dx[4] = {0, 0, 1, -1};
 19 const int dy[4] = {1, -1, 0, 0};
 20  
 21 struct edge {
 22   int next, to, f;
 23   edge() {}
 24   edge(int _n, int _t, int _f) : next(_n), to(_t), f(_f) {}
 25 } e[M];
 26  
 27 int first[N], tot = 1;
 28 int n, S, T, P, Q, R, D;
 29 int f[45][45][45];
 30 int d[N], q[N];
 31  
 32 inline int read() {
 33   int x = 0, sgn = 1;
 34   char ch = getchar();
 35   while (ch < '0' || '9' < ch) {
 36     if (ch == '-') sgn = -1;
 37     ch = getchar();
 38   }
 39   while ('0' <= ch && ch <= '9') {
 40     x = x * 10 + ch - '0';
 41     ch = getchar();
 42   }
 43   return sgn * x;
 44 }
 45  
 46 inline void Add_Edges(int x, int y, int z) {
 47   e[++tot] = edge(first[x], y, z), first[x] = tot;
 48   e[++tot] = edge(first[y], x, 0), first[y] = tot;
 49 }
 50  
 51 inline int p(int x, int y, int z) {
 52   return z == 0 ? S : (z - 1) * P * Q + (x - 1) * Q + y;
 53 }
 54  
 55 void build_graph() {
 56   int i ,j, k, l, X, Y;
 57   for (i = 1; i <= P; ++i)
 58     for (j = 1; j <= Q; ++j) {
 59       for (k = 1; k <= R; ++k) {
 60     Add_Edges(p(i, j, k - 1), p(i, j, k), f[i][j][k]);
 61     if (k > D)
 62       for (l = 0; l < 4; ++l) {
 63         X = i + dx[l], Y = j + dy[l];
 64         if (X < 1 || Y < 1 || X > P || Y > Q) continue;
 65         Add_Edges(p(i, j, k), p(X, Y, k - D), inf);
 66       }
 67       }
 68       Add_Edges(p(i, j, R), T, inf);
 69     }
 70 }
 71  
 72 #define y e[x].to
 73 #define p q[l]
 74 bool bfs() {
 75   int l, r, x;
 76   memset(d, -1, sizeof(d));
 77   d[q[1] = S] = 1;
 78   for (l = r = 1; l != r + 1; ++l)
 79     for (x = first[p]; x; x = e[x].next)
 80       if (!~d[y] && e[x].f) {
 81     d[q[++r] = y] = d[p] + 1;
 82     if (y == T) return 1;
 83       }
 84   return 0;
 85 }
 86 #undef p
 87  
 88 int dfs(int p, int lim) {
 89   if (p == T || !lim) return lim;
 90   int x, tmp, rest = lim;
 91   for (x = first[p]; x && rest; x = e[x].next) 
 92     if (d[y] == d[p] + 1 && ((tmp = min(e[x].f, rest)) > 0)) {
 93       rest -= (tmp = dfs(y, tmp));
 94       e[x].f -= tmp, e[x ^ 1].f += tmp;
 95       if (!rest) return lim;
 96     }
 97   if (rest) d[p] = -1;
 98   return lim - rest;
 99 }
100 #undef y
101  
102 int Dinic() {
103   int res = 0;
104   while (bfs())
105     res += dfs(S, inf);
106   return res;
107 }
108  
109 int main() {
110   int i, j, k;
111   P = read(), Q = read(), R = read(), D = read();
112   S = P * Q * R + 1, T = S + 1;
113   for (i = 1; i <= R; ++i)
114     for (j = 1; j <= P; ++j)
115       for (k = 1; k <= Q; ++k)
116     f[j][k][i] = read();
117   build_graph();
118   printf("%d
", Dinic());
119   return 0;
View Code
By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
原文地址:https://www.cnblogs.com/rausen/p/4293877.html