HDU-3046 Pleasant sheep and big big wolf 网络流,最小割
第一道网络流的应用题,题中要求出至少要多少个围墙才能把狼阻挡在羊群活动的范围外,解决该题的方法就是以狼为源点,羊会汇点,求最小割即为最少的围墙数。出源点和汇点外其余两个网格之间的权值都是1,表示有一头狼能够通过网格走到羊群中去。
递归写的sap一直超时,最后还是递归的Dinic过了,无语了。不会非递归伤不起啊。
代码如下:
#include <cstring> #include <cstdlib> #include <cstring> #include <algorithm> #include <cstdio> #include <queue> #define RE(x) (x)^1 #define INF 0x3fffffff #define MAXN 205 using namespace std; int N, M, G[MAXN][MAXN], dis[MAXN*MAXN]; int dir[2][2] = {0, 1, 1, 0}; int idx, head[MAXN*MAXN]; const int sink = MAXN*MAXN-1, source = MAXN*MAXN-2; struct Edge { int v, cap, next; }e[MAXN*MAXN*4]; inline void init() { idx = -1; memset(head, 0xff, sizeof (head)); } inline int to(int x, int y) { return (x-1)*M+(y-1); } inline void insert(int a, int b, int c) { ++idx; e[idx].v = b, e[idx].cap = c; e[idx].next = head[a], head[a] = idx; } inline bool judge(int x, int y) { if (x < 1 || x > N || y < 1 || y > M) { return false; } return true; } inline void getint(int &t) { char c; while (c = getchar(), c < '0' || c > '9') ; t = c - '0'; while (c = getchar(), c >= '0' && c <= '9') { t = t * 10 + c - '0'; } } inline void check(int x, int y) { int xx, yy; if (G[x][y] == 1) { insert(to(x, y), sink, INF); insert(sink, to(x, y), 0); } else if (G[x][y] == 2) { insert(source, to(x, y), INF); insert(to(x, y), source, 0); } for (int i = 0; i < 2; ++i) { xx = x + dir[i][0], yy = y + dir[i][1]; if (judge(xx, yy)) { insert(to(x, y), to(xx, yy), 1); insert(to(xx, yy), to(x, y), 1); } } } bool bfs() { int pos; queue<int>q; memset(dis, 0xff, sizeof (dis)); dis[source] = 0; q.push(source); while (!q.empty()) { pos = q.front(); q.pop(); for (int i = head[pos]; i != -1; i = e[i].next) { if (dis[e[i].v] == -1 && e[i].cap > 0) { dis[e[i].v] = dis[pos]+1; q.push(e[i].v); } } } return dis[sink] != -1; } int dfs(int u, int flow) { if (u == sink) { return flow; } int tf = 0, sf; for (int i = head[u]; i != -1; i = e[i].next) { if (dis[u]+1 == dis[e[i].v] && e[i].cap > 0 && (sf = dfs(e[i].v, min(flow-tf, e[i].cap)))) { e[i].cap -= sf, e[RE(i)].cap += sf; tf += sf; if (tf == flow) { return flow; } } } if (!tf) { dis[u] = -1; } return tf; } int dinic() { int ans = 0; while (bfs()) { ans += dfs(source, INF); } return ans; } int main() { int ca = 0; while (scanf("%d %d", &N, &M) == 2) { init(); for (int i = 1; i <= N; ++i) { for (int j = 1; j <= M; ++j) { scanf("%d", &G[i][j]); // getint(G[i][j]); } } for (int i = 1; i <= N; ++i) { for (int j = 1; j <= M; ++j) { check(i, j); } } printf("Case %d:\n%d\n", ++ca, dinic()); } return 0; }