您的位置:首页 > 其它

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

2016-08-11 22:41 465 查看
原题链接: 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: