bzoj 1412 最小割
思路:一个篱笆的作用就是堵死一条路,我们将S与狼建边,权值为inf, 将羊与T建边,权值为inf, 每个点与其可以到的路建边,权值为1,
然后跑最小割,因为如果S到T有通路说明狼肯定可以到羊,每一个割代表一个篱笆。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int, int> using namespace std; const int N = 2e4 + 7; const int M = 2e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; int n, m, S, T, tot, level[N], head[N], a[101][101], id[101][101]; int dx[] = {0, 0, 1, -1}, dy[] = {1, -1, 0, 0}; struct Edge { int to, w, nx; }edge[M << 1]; void add(int u, int v, int w) { edge[tot].to = v; edge[tot].w = w; edge[tot].nx = head[u]; head[u] = tot++; edge[tot].to = u; edge[tot].w = 0; edge[tot].nx = head[v]; head[v] = tot++; } bool bfs() { memset(level, 0, sizeof(level)); queue<int> que; que.push(S), level[S] = 1; while(!que.empty()) { int u = que.front(); que.pop(); if(u == T) return true; for(int i = head[u]; ~i; i = edge[i].nx) { int v = edge[i].to, w = edge[i].w; if(level[v] || w <= 0) continue; level[v] = level[u] + 1; que.push(v); } } return false; } int dfs(int u, int p) { if(u == T) return p; int ret = 0; for(int i = head[u]; ~i; i = edge[i].nx) { int v = edge[i].to, w = edge[i].w; if(level[v] != level[u] + 1 || w <= 0) continue; int f = dfs(v, min(p - ret, w)); ret += f; edge[i].w -= f; edge[i ^ 1].w += f; if(ret == p) break; } if(!ret) level[u] = 1; return ret; } int Dinic() { int ans = 0; while(bfs()) ans += dfs(S, inf); return ans; } void init() { tot = 0; memset(head, -1, sizeof(head)); } bool check(int x, int y) { if(x < 1 || x > n) return false; if(y < 1 || y > m) return false; return true; } int main() { init(); scanf("%d%d", &n, &m); S = 0, T = n * m + 1; for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { scanf("%d", &a[i][j]); id[i][j] = (i - 1) * m + j; if(a[i][j] == 1) add(S, id[i][j], inf); else if(a[i][j] == 2) add(id[i][j], T, inf); } } for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { for(int k = 0; k < 4; k++) { int x = i + dx[k], y = j + dy[k]; if(check(x, y) && (a[i][j] != a[x][y] || !a[i][j] && !a[x][y])) { add(id[i][j], id[x][y], 1); } } } } printf("%d\n", Dinic()); return 0; } /* */