bzoj2132: 圈地计划

要分成两坨对吧。。 所以显然最小割

但是不兹辞啊。。

最小割是最小的啊 求最大费用怎么玩啊

那咱们就把所有费用都加起来,减掉一个最小的呗

但是两个属于不同集合的点贡献的价值是负的啊

网络流怎么跑负的啊

那咱就交换一下呗

原图是二分图啊,把另一部分与S和T连边的流量换一下就好啦。

注意哦 n和m可能为1 所以累加C的时候写成ans += C[i][j] * (4 - (i == 1 || i == n) - (j == 1 || j == m));就错啦。

要么在加边的时候累加,要么写成ans += C[i][j] * ((i != 1) + (i != n) + (j != 1) + (j != m)); 

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<algorithm>
  5 #include<iostream>
  6 #define rep(i, a, b) for(int i = (a), _end = (b); i <= _end; ++i)
  7 
  8 using namespace std;
  9 
 10 void setIO(const string& s) {
 11     freopen((s + ".in").c_str(), "r", stdin);
 12     freopen((s + ".out").c_str(), "w", stdout);
 13 }
 14 template<typename Q> Q read(Q& x) {
 15     static char c, f;
 16     for(f = 0; c = getchar(), !isdigit(c); ) if(c == '-') f = 1;
 17     for(x = 0; isdigit(c); c = getchar()) x = x * 10 + c - '0';
 18     if(f) x = -x;
 19     return x;
 20 }
 21 template<typename Q> Q read() {
 22     static Q x; read(x); return x;
 23 }
 24 
 25 // ISAP
 26 const int N = 100 * 100 + 10, M = 100 * 100 * 4 + 10, INF = ~0u >> 1;
 27 
 28 struct Edge {
 29     int to, adv;
 30     Edge *next;
 31     Edge(int to = 0, int adv = 0, Edge *next = 0) : to(to), adv(adv), next(next) {}
 32 }pool[M * 2], *pis = pool, *fir[N], *pre[N];
 33 
 34 void AddEdge(int u, int v, int w, int b = 0) {
 35     fir[u] = new(pis++) Edge(v, w, fir[u]);
 36     fir[v] = new(pis++) Edge(u, w * b, fir[v]);
 37 }
 38 
 39 Edge *inv(Edge *p) {
 40     return pool + ((p - pool) ^ 1);
 41 }
 42 
 43 int d[N], q[N], ql, qr;
 44 
 45 namespace ISAP {
 46     int n, s, t;
 47     int num[N];
 48     Edge *cur[N];
 49     
 50     void insert(int u, int dis) {
 51         if(d[u] == n) {
 52             d[u] = dis;
 53             q[qr++] = u;
 54         }
 55     }
 56     
 57     void BFS() {
 58         for(int u = 1; u <= n; u++) {
 59             d[u] = n;
 60         }
 61         ql = qr = 0;
 62         insert(t, 0);
 63         while(ql ^ qr) {
 64             int u = q[ql++];
 65             for(Edge *p = fir[u]; p; p = p->next) if(inv(p)->adv){
 66                 insert(p->to, d[u] + 1);
 67             }
 68         }
 69     }
 70     
 71     int Augment() {
 72         int a = INF;
 73         for(int u = t; u != s; u = inv(pre[u])->to) {
 74             a = min(a, pre[u]->adv);
 75         }
 76         for(int u = t; u != s; u = inv(pre[u])->to) {
 77             pre[u]->adv -= a;
 78             inv(pre[u])->adv += a;
 79         }
 80         return a;
 81     }
 82     
 83     int Maxflow() {
 84         memset(num, 0, sizeof num);
 85         BFS();
 86         for(int u = 1; u <= n; u++) {
 87             cur[u] = fir[u];
 88             num[d[u]]++;
 89         }
 90         for(int i = 1; i < d[s]; i++) {
 91             if(!num[i]) return 0;
 92         }
 93         int flow = 0;
 94         for(int u = s; d[s] < n; ) {
 95             if(u == t) {
 96                 flow += Augment();
 97                 u = s;
 98             }
 99             int ok = 0;
100             for(Edge *&p = cur[u]; p; p = p->next) if(p->adv) {
101                 int v = p->to;
102                 if(d[v] + 1 == d[u]) {
103                     pre[u = v] = p;
104                     ok = 1;
105                     break;
106                 }
107             }
108             if(!ok) {
109                 int &dis = d[u];
110                 if(!--num[dis]) break;
111                 dis = n;
112                 for(Edge *p = (cur[u] = fir[u]); p; p = p->next) if(p->adv) {
113                     dis = min(dis, d[p->to] + 1);
114                 }
115                 num[dis]++;
116                 if(u != s) u = inv(pre[u])->to;
117             }
118         }
119         return flow;
120     }
121     
122     int main(int _n, int _s, int _t) {
123         n = _n, s = _s, t = _t;
124         return Maxflow();
125     }
126 }
127 
128 int n, m;
129 
130 int encode(int x, int y) {
131     return (x - 1) * m + y;
132 }
133 
134 const int maxn = 100 + 10;
135 
136 int A[maxn][maxn], B[maxn][maxn], C[maxn][maxn];
137 
138 int main() {
139 #ifdef DEBUG
140     freopen("in.txt", "r", stdin);
141     freopen("out.txt", "w", stdout);
142 #endif
143     
144     read(n), read(m);
145     int ans = 0;
146     rep(i, 1, n) rep(j, 1, m) ans += read(A[i][j]);
147     rep(i, 1, n) rep(j, 1, m) ans += read(B[i][j]);
148     rep(i, 1, n) rep(j, 1, m) read(C[i][j]);
149     int s = n * m + 1, t = s + 1;
150     rep(i, 1, n) rep(j, 1, m) {
151         int u = encode(i, j);
152         if((i ^ j) & 1) swap(A[i][j], B[i][j]);
153         AddEdge(s, u, A[i][j]);
154         AddEdge(u, t, B[i][j]);
155         if(i < n) AddEdge(u, encode(i + 1, j), C[i][j] + C[i+1][j], 1), ans += C[i][j] + C[i+1][j];
156         if(j < m) AddEdge(u, encode(i, j + 1), C[i][j] + C[i][j+1], 1), ans += C[i][j] + C[i][j+1];
157     }
158     
159     printf("%d
", ans - ISAP::main(t, s, t));
160     
161     return 0;
162 }
View Code
原文地址:https://www.cnblogs.com/showson/p/5043565.html