网络流复习计划
既然是复习网络流,那就不会去做水题了吧233
A.BZOJ3996 TJOI2015线性代数
看到题就被吓坏了2333。线性代数根本没看完好吗?
然后。。。
MD转个模型就是网络流了
“题目大意:给定一个n∗n的矩阵B和一个1∗n的行向量C,求一个1∗n的01矩阵A,使(A×B−C)×AT最大
(A×B−C)×AT=A×B×AT−C×AT
我们可以考虑有n个物品,每个物品选不选对应A中每个位置是1还是0
那么行向量C可以看做每个物品的代价 而矩阵B可以看做同时选择某两个物品时的收益
那么这个模型就被我们直接分析出来了,网络流走起~”
————PoPoQQQ
就是这样喵(我没有卖萌
1 #include<bits/stdc++.h> 2 #define N 300300 3 #define M 2002002 4 using namespace std; 5 int n, m, cnt = 1, ans, tmp; 6 int c[M], e[M], nxt[M], last[M]; 7 int dis[M]; 8 9 int read() { 10 int x = 0, f = 1; char ch = getchar(); 11 while (!isdigit(ch)) { 12 if (ch == '-') f = -1; ch = getchar(); 13 } 14 while (isdigit(ch)) { 15 x = x * 10 + ch - '0'; ch = getchar(); 16 } 17 return x * f; 18 } 19 20 void add(int x,int y,int z) { 21 e[++cnt] = y; c[cnt] = z; nxt[cnt] = last[x]; last[x] = cnt; 22 } 23 24 int BFS() { 25 for (int i = 0; i < M; i ++) { 26 dis[i] = -1; 27 } 28 dis[0] = 1; 29 queue<int> Q; 30 while (!Q.empty()) { 31 Q.pop(); 32 } 33 Q.push(0); 34 while (!Q.empty()) { 35 int x = Q.front(); 36 Q.pop(); 37 for(int i = last[x]; i; i = nxt[i]) 38 if(c[i] && !~dis[e[i]]) { 39 dis[e[i]] = dis[x] + 1; 40 Q.push(e[i]); 41 if(e[i] == N - 1) return 1; 42 } 43 } 44 return 0; 45 } 46 47 int Get(int x, int flow) { 48 int low = flow; 49 if (x == (N - 1)) return flow; 50 for(int i = last[x]; i && low; i = nxt[i]) 51 if(c[i] && dis[e[i]] == dis[x] + 1) { 52 int temp = Get(e[i], min(low, c[i])); 53 low -= temp; 54 c[i] -= temp; 55 c[i ^ 1] += temp; 56 } 57 if (low) dis[x] = -1; 58 return flow - low; 59 } 60 61 int main() { 62 memset(c, 0, sizeof(c)); 63 n = read(); ans = 0; 64 for (int i = 1; i <= n; i ++) 65 for (int j = 1; j <= n; j ++) { 66 int x = read(); ans += x; 67 add(0, i * n + j, x); add(i * n + j, 0, 0); 68 add(i * n + j, i, 0x3f3f3f3f); add(i, i * n + j, 0); 69 add(i * n + j, j, 0x3f3f3f3f); add(j, i * n + j, 0); 70 } 71 for (int i = 1; i <= n; i ++) { 72 int x = read(); 73 add(i, N - 1, x); add(N - 1, i, 0); 74 } 75 while (BFS()) { 76 ans -= Get(0, 0x3f3f3f3f); 77 } 78 printf("%d\n", ans); 79 return 0; 80 }