hdu3046 Pleasant sheep and big big wolf--Dinic算法 & 最小割

来源:互联网 发布:陕西seo服务公司 编辑:程序博客网 时间:2024/05/17 03:42

原题链接: http://acm.hdu.edu.cn/showproblem.php?pid=3046


题意:

n*m的矩阵中,把狼和羊放进格子中,一个格子一个动物,要求建围栏把狼困住,不能吃掉羊。建图即可,这也是难点,设置一个超级源点和超级汇点,源点指向所有狼,所有羊指向汇点,然后求最小切割就行了,当然了两个点的边权值都要设为无穷大,这样求解最小割就没问题了。


#define _CRT_SECURE_NO_DEPRECATE #include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<cmath>#include<queue>using namespace std;struct Node{int v;int w;int next;}node[40000 * 4 + 100];int n, m;int cas = 1;int head[40010];int d[40010 * 4];int q[40010];int h, r;int num;int s, t;void add(int u, int v, int w){node[num].v = v;node[num].w = w;node[num].next = head[u];head[u] = num++;node[num].v = u;node[num].w = 0;node[num].next = head[v];head[v] = num++;}bool bfs(){memset(d, 0, sizeof(d));d[s] = 1;h = 0;r = 1;q[1] = s;while (h < r){int u = q[++h];for (int i = head[u]; i != -1; i = node[i].next){int v = node[i].v;if (d[v] == 0 && node[i].w>0){d[v] = d[u] + 1;q[++r] = v;}}}if (d[t])return 1;return 0;}int dfs(int u, int flow){int a = 0;int ans = 0;if (u == t)return flow;for (int i = head[u]; i != -1; i = node[i].next){int v = node[i].v;if (node[i].w > 0 && d[v] == d[u] + 1 && (a = dfs(v, min(flow, node[i].w)))){node[i].w -= a;node[i ^ 1].w += a;ans += a;if (ans == flow)//u节点下的路线找到的值等于u节点前最小权值,u节点以后的路线就不用找了return flow;}}if (ans == 0)//如果找不到,该路线就不用找了,直接赋值0,断开该路d[u] = 0;return ans;}int dinic(){int sum = 0;int temp = 0;while (bfs())sum += dfs(s, INT_MAX);return sum;}int main(){int x;while (~scanf("%d%d", &n, &m)){memset(head, -1, sizeof(head));num = 0;s = 0;t = n*m + 1;for (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++){scanf("%d", &x);if (x == 1)add(s, (i - 1)*m + j, INT_MAX);else if (x == 2)add((i - 1)*m + j, t, INT_MAX);if (i - 1 >= 1)add((i - 1)*m + j, (i - 2)*m + j, 1);if (i + 1 <= n)add((i - 1)*m + j, i*m + j, 1);if (j - 1 >= 1)add((i - 1)*m + j, (i - 1)*m + j - 1, 1);if (j + 1 <= m)add((i - 1)*m + j, (i - 1)*m + j + 1, 1);}}printf("Case %d:\n%d\n", cas++, dinic());}return 0;}





1 0
原创粉丝点击