BZOJ 1412[ZJOI2009]狼和羊的故事 - 最小割
题解
源点$S$连向狼的领地, 羊的领地连向汇点$T$, 再从每个位置连向相邻的位置。
跑一边最大流就可以的出答案
代码
1 #include<cstring> 2 #include<iostream> 3 #include<cstdio> 4 #include<algorithm> 5 #include<queue> 6 #define rd read() 7 #define rep(i,a,b) for( int i = (a); i <= (b); ++i) 8 #define per(i,a,b) for(int i = (a); i >= (b); --i) 9 using namespace std; 10 11 const int N = 5e4, inf = ~0U >> 2; 12 int head[N], S, T, dep[N], tot, n, m, mp[105][105], ans; 13 int dx[4] = {0, 0, -1, 1}, dy[4] = {1, -1, 0, 0}; 14 15 queue<int> q; 16 17 struct edge { 18 int nxt, to, val; 19 }e[N << 2]; 20 21 int read() { 22 int X = 0, p = 1;char c = getchar(); 23 for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = - 1; 24 for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0'; 25 return X * p; 26 } 27 28 int ch(int x) { 29 return ((x + 1) ^ 1) - 1; 30 } 31 32 int tn(int x, int y) { 33 return (x - 1) * m + y; 34 } 35 36 void added(int fr, int to, int val) { 37 e[++tot].to = to; 38 e[tot].val = val; 39 e[tot].nxt = head[fr]; 40 head[fr] = tot; 41 } 42 43 void add(int fr, int to, int val) { 44 added(fr, to, val); 45 added(to, fr, 0); 46 } 47 48 int bfs() { 49 memset(dep, 0, sizeof(dep)); 50 dep[S] = 1; 51 q.push(S); 52 for(int u, nt; !q.empty(); ) { 53 u = q.front(); q.pop(); 54 for(int i = head[u]; i; i = e[i].nxt ) { 55 nt = e[i].to; 56 if(dep[nt] || !e[i].val) continue; 57 dep[nt] = dep[u] + 1; 58 q.push(nt); 59 } 60 } 61 return dep[T]; 62 } 63 64 int dfs(int u, int flow) { 65 if(u == T) return flow; 66 if(!flow) return 0; 67 int add = 0; 68 for(int i = head[u]; i && add < flow; i = e[i].nxt) { 69 int nt = e[i].to; 70 if(dep[nt] != dep[u] + 1 || !e[i].val) continue; 71 int tmp = dfs(nt, min(flow - add, e[i].val)); 72 add += tmp; 73 e[i].val -= tmp; 74 e[ch(i)].val += tmp; 75 } 76 return add; 77 } 78 79 int main() 80 { 81 n = rd; m = rd; 82 T = n * m * 3; 83 rep(i, 1, n) rep(j, 1, m) { 84 mp[i][j] = rd; 85 if(mp[i][j] == 1) add(S, tn(i, j), inf); 86 if(mp[i][j] == 2) add(tn(i, j), T, inf); 87 } 88 rep(i, 1, n) rep(j, 1, m) rep(k, 0, 3) { 89 int nx = i + dx[k], ny = j + dy[k]; 90 if(!nx || !ny || nx > n || ny > m) continue; 91 add(tn(i, j), tn(nx, ny), 1); 92 } 93 for(; bfs(); ) ans += dfs(S, inf); 94 printf("%d\n", ans); 95 }