很明显的一道网络流题。。
首先把所有值的加起来,再减掉网络流最小割值就好了,问题就是如何建图。这貌似也是考了好多次了的。。。
把每个人抽象成一个点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\n", ans - Dinic()); 121 return 0; 122 }
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen