就是求$D = A \times B \times A^T - C \times A^T$
展开也就是$$D = \sum_{i, j} A_i * A_j * B_{i, j} - \sum_{i} C_i * A_i$$
其中$Ai = 0 \ or \ 1$
转化成最小割模型,就是一堆东西,选了$i$号物品要支付费用$C_i$,同时选$i$和$j$两个物品可以获得$B_{i, j}$的收益
于是非常简单啦,建图什么的直接看程序好了!
1 /************************************************************** 2 Problem: 3996 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:476 ms 7 Memory:51612 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cstring> 12 #include <algorithm> 13 14 using namespace std; 15 const int N = 505 * 505; 16 const int M = N << 4; 17 const int inf = 1e9; 18 19 struct edge { 20 int next, to, f; 21 edge() {} 22 edge(int _n, int _t, int _f) : next(_n), to(_t), f(_f) {} 23 } e[M]; 24 25 int n, ans, S, T; 26 int first[N], tot = 1; 27 int d[N], q[N]; 28 29 inline int read(); 30 31 inline void Add_Edges(int x, int y, int f) { 32 e[++tot] = edge(first[x], y, f), first[x] = tot; 33 e[++tot] = edge(first[y], x, 0), first[y] = tot; 34 } 35 36 #define y e[x].to 37 #define p q[l] 38 bool bfs() { 39 int l, r, x; 40 memset(d, -1, sizeof(d)); 41 d[q[1] = S] = 1; 42 for (l = r = 1; l != r + 1; ++l) 43 for (x = first[p]; x; x = e[x].next) 44 if (!~d[y] && e[x].f) { 45 d[q[++r] = y] = d[p] + 1; 46 if (y == T) return 1; 47 } 48 return 0; 49 } 50 #undef p 51 52 int dfs(int p, int lim) { 53 if (p == T || !lim) return lim; 54 int x, tmp, rest = lim; 55 for (x = first[p]; x && rest; x = e[x].next) 56 if (d[y] == d[p] + 1 && ((tmp = min(e[x].f, rest)) > 0)) { 57 rest -= (tmp = dfs(y, tmp)); 58 e[x].f -= tmp, e[x ^ 1].f += tmp; 59 if (!rest) return lim; 60 } 61 if (rest) d[p] = -1; 62 return lim - rest; 63 } 64 #undef y 65 66 int Dinic() { 67 int res = 0; 68 while (bfs()) 69 res += dfs(S, inf); 70 return res; 71 } 72 73 int main() { 74 int i, j, x, now; 75 n = now = read(), S = n * n + n + 1, T = S + 1; 76 for (i = 1; i <= n; ++i) 77 for (j = 1; j <= n; ++j) { 78 x = read(), ++now; 79 Add_Edges(i, now, inf), Add_Edges(j, now, inf); 80 Add_Edges(now, T, x); 81 ans += x; 82 } 83 for (i = 1; i <= n; ++i) Add_Edges(S, i, read()); 84 printf("%d\n", ans - Dinic()); 85 return 0; 86 } 87 88 inline int read() { 89 static int x; 90 static char ch; 91 x = 0, ch = getchar(); 92 while (ch < ‘0‘ || ‘9‘ < ch) 93 ch = getchar(); 94 while (‘0‘ <= ch && ch <= ‘9‘) { 95 x = x * 10 + ch - ‘0‘; 96 ch = getchar(); 97 } 98 return x; 99 }
原文:http://www.cnblogs.com/rausen/p/4454595.html