HDU-3046-Pleasant sheep and big big wolf(理解最小割模板)

题目
在怒江,有一个著名的草原。它还能吸引可爱的羊和它的伙伴们去度假。大灰狼和他的家人知道了这件事,悄悄地躲进了大草坪。作为ZJNU ACM/ICPC团队的一员,我们有义务保护好喜羊羊和它的伙伴们,不被大灰狼打扰。我们决定建造一些长度为1的单位栅栏。任何狼和羊都不能越过篱笆。当然,一个网格只能包含一个动物。

现在,我们要求设置最小的栅栏,让喜羊羊和他的伙伴们免受大灰狼和他的伙伴们的打扰。
在这里插入图片描述

输入
有很多情况。
对每一个案例:
N和M(N,M < = 200)
N * M矩阵:
0是空的,1是喜羊羊和他的伙伴,2是大灰狼和他的伙伴。

输出
对每一个案例:

第一行输出“Case p:”,p为第p种情况;
第二行是答案。

Sample Input

4 6
1 0 0 1 0 0
0 1 1 0 0 0
2 0 0 0 0 0
0 2 0 1 1 0

Sample Output

Case 1:
4

喜羊羊向t建容量为4或大于4 INF的边。。。 灰太狼向s建容量为4或大于4 INF的边
代表要从狼出发到羊 所以是最小割
每个格子向相邻的格子建容量为1的边

#include <queue>
#include <cstring>
#include <cstdio>
#define  m(a,b) memset(a,b,sizeof a)
using namespace std;
const int N=45000;
const int INF=0x3f3f3f3f;
struct Edge{int to,len,nex;}edge[N*10];
int head[N],d[N];
int tot,s,t;
void add(int from,int to,int len)
{
    edge[++tot]=(Edge){to,len,head[from]};head[from]=tot;
    edge[++tot]=(Edge){from,0,head[to]};head[to]=tot;
}
queue<int>q;
bool bfs()
{
    while(!q.empty())
        q.pop();
    m(d,0);
    q.push(s);
    d[s]=1;
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        for(int i=head[x];i;i=edge[i].nex)
        {
            int y=edge[i].to,l=edge[i].len;
            if(!d[y]&&l)
            {
                d[y]=d[x]+1;
                q.push(y);
                if(y==t)
                    return 1;
            }
        }
    }
    return 0;
}
int dinic(int x,int flow)
{
    if(x==t)
        return flow;
    int res=flow,k;
    for(int i=head[x];i&&res;i=edge[i].nex)
    {
        int y=edge[i].to,l=edge[i].len;
        if(l&&d[y]==d[x]+1)
        {
            k=dinic(y,min(res,l));
            if(!k)
            {
                d[y]=0;
                continue;
            }
            edge[i].len-=k;
            edge[i^1].len+=k;
            res-=k;
        }
    }
    return flow-res;
}
int main()
{
    int n,m,cas=0;
    while(~scanf("%d%d",&n,&m))
    {

        m(head,0);
        tot=1;
        s=0,t=n*m+1;
        int x;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                int x;
                scanf("%d",&x);
                int k=(i-1)*m+j;
                if(i>1)
                    add(k,k-m,1);
                if(i<n)
                    add(k,k+m,1);
                if(j>1)
                    add(k,k-1,1);
                if(j<m)
                    add(k,k+1,1);
                if(x==1)
                    add(k,t,4);
                if(x==2)
                    add(s,k,4);
            }
        int maxflow=0;
        while(bfs())
            maxflow+=dinic(s,INF);
        printf("Case %d:\n%d\n",++cas,maxflow);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42576687/article/details/87293672