[Square access network flow problem] [24] Minimal Cut

 

 

Sample input and output

Input # 1
3 3
1 2 3
3 2 3
2 3 1 
Output # 1
11

 

 

Thinking

  To ensure a point because he can not have a common point of contact with the edge

  It is easy to think of all the points are divided into two camps

  Obviously a horizontal and vertical coordinates of the point of addition is an even number

  Horizontal and vertical coordinates point contact therewith adding odd

  Thereby obtaining the divided bipartite graph by: parity addition and the horizontal and vertical coordinates

  The even-even camp side S, the odd and even sides camp T

  Even parity between the sides INF camp

  This model is a bipartite graph kick

  It can be found by observing the figures to S, T and even a choice symbol rim

  When the two sides have common points can circulate, clearly does not meet the requirements of

  Consider removing this side and minimize cost

  I found it to be a minimum cut problem

  Between adjacent dots connected by flow inf edges must be cut off can be guaranteed even edge to a point S or T

  This time the answer is equal to the total weight of all the points and - minimum cut = SUM - MAXFLOW

 

CODE

 

  1 #include <bits/stdc++.h>
  2 #define dbg(x) cout << #x << "=" << x << endl
  3 #define eps 1e-8
  4 #define pi acos(-1.0)
  5 
  6 using namespace std;
  7 typedef long long LL;
  8 
  9 const LL inf = 0x7f7f7f7f;
 10 
 11 template<class T>inline void read(T &res)
 12 {
 13     char c;T flag=1;
 14     while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
 15     while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
 16 }
 17 
 18 namespace _buff {
 19     const size_t BUFF = 1 << 19;
 20     char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
 21     char getc() {
 22         if (ib == ie) {
 23             ib = ibuf;
 24             ie = ibuf + fread(ibuf, 1, BUFF, stdin);
 25         }
 26         return ib == ie ? -1 : *ib++;
 27     }
 28 }
 29 
 30 int qread() {
 31     using namespace _buff;
 32     int ret = 0;
 33     bool pos = true;
 34     char c = getc();
 35     for (; (c < '0' || c > '9') && c != '-'; c = getc()) {
 36         assert(~c);
 37     }
 38     if (c == '-') {
 39         pos = false;
 40         c = getc();
 41     }
 42     for (; c >= '0' && c <= '9'; c = getc()) {
 43         ret = (ret << 3) + (ret << 1) + (c ^ 48);
 44     }
 45     return pos ? ret : -ret;
 46 }
 47 
 48 const int maxn = 200007;
 49 
 50 int n, m;
 51 int s, t;
 52 
 53 struct edge{
 54     int from,to;
 55     LL cap,flow;
 56 };
 57 
 58 struct DINIC {
 59     int head[maxn << 1], nxt[maxn << 1], edge[maxn << 1], cnt;
 60     int cap[maxn << 1], depth[maxn << 1];
 61 
 62     void init() {
 63         cnt = 1;
 64         memset(head, 0, sizeof(head));
 65     }
 66 
 67     void BuildGraph(int u, int v, int w) {
 68         ++cnt;
 69         edge[cnt] = v;
 70         nxt[cnt] = head[u];
 71         cap[cnt] = w;
 72         head[u] = cnt;
 73 
 74         ++cnt;
 75         edge[cnt] = u;
 76         nxt[cnt] = head[v];
 77         cap[cnt] = 0;
 78         head[v] = cnt;
 79     }
 80 
 81     queue<int> q;
 82 
 83     bool bfs() {
 84         memset(depth, 0, sizeof(depth));
 85         depth[s] = 1;
 86         q.push(s);
 87         while(!q.empty()) {
 88             int u = q.front();
 89             q.pop();
 90             for ( int i = head[u]; i; i = nxt[i] ) {
 91                 int v = edge[i];
 92                 if(depth[v]) {
 93                     continue;
 94                 }
 95                 if(cap[i]) {
 96                     depth[v] = depth[u] + 1;
 97                     q.push(v);
 98                 }
 99             }
100         }
101         //printf("dep[%d]:%d\n",t, depth[t]);
102         return depth[t];
103     }
104 
105     int dfs(int u, int dist) {
106         if(u == t) {
107             return dist;
108         }
109         int flow = 0;
110         for ( int i = head[u]; i && dist; i = nxt[i] ) {
111             if(cap[i] == 0)
112                 continue;
113             int v = edge[i];
114             if(depth[v] != depth[u] + 1) {
115                 continue;
116             }
117             int res = dfs(v, min(cap[i], dist));
118             cap[i] -= res;
119             cap[i ^ 1] += res;
120             //printf("cap[%d]:%d\n",t, cap[t]);
121             dist -= res;
122             flow += res;
123         }
124         return flow;
125     }
126 
127     int maxflow() {
128         int ans = 0;
129         while(bfs()) {
130             ans += dfs(s, inf);
131         }
132         return ans;
133     }
134 } dinic;
135 
136 int dr[4] = {1, 0, -1, 0};
137 int dc[4] = {0, 1, 0, -1};
138 
139 inline int id(int a, int b) {
140     return (a - 1) * n + b;
141 }
142 
143 int main()
144 {
145     //freopen("data.txt", "r", stdin);
146     read(m); read(n);
147     int sum = 0;
148     s = 0, t = n * m + 1;
149     dinic.init();
150     for ( int i = 1; i <= m; ++i ) {
151         for ( int j = 1; j <= n; ++j ) {
152             int x;
153             read(x);
154             sum += x;
155             if(((i + j) & 1) == 0) {
156                 dinic.BuildGraph(s, id(i, j), x);
157                 for ( int k = 0; k < 4; ++k ) {
158                     int xx = i + dr[k], yy = j + dc[k];
159                     if(xx <= m && xx >= 1 && yy <= n && yy >= 1) {
160                         dinic.BuildGraph(id(i, j), id(xx, yy), inf);
161                     }
162                     
163                 }
164             }
165             else {
166                 dinic.BuildGraph(id(i, j), t, x);
167             }
168         }
169     }
170     int res = dinic.maxflow();
171     //dbg(res);
172     cout << sum - res << endl;
173     return 0;
174 }
View Code

 

Guess you like

Origin www.cnblogs.com/orangeko/p/12670800.html