BZOJ3894 文理分科

很明显的一道网络流题。。

首先把所有值的加起来,再减掉网络流最小割值就好了,问题就是如何建图。这貌似也是考了好多次了的。。。

把每个人抽象成一个点p,则

先是S向p连边,流量为选文科的高兴值,p向T连边,流量为选理科的高兴值。

然后是same的条件,对每个人新建两个点p1, p2

S向p1连边,流量为文科same的高兴值,p1向相邻点和自己的p连边,流量为inf

p2相T连边,流量为理科same的高兴值,相邻点和自己的p向p2连边,流量为inf

然后跑一下网络流就好了(蒟蒻tot = 1没写调了半天还以为建图错了= =b)

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