洛谷P2598 [ZJOI2009]狼和羊的故事

题目描述

“狼爱上羊啊爱的疯狂,谁让他们真爱了一场;狼爱上羊啊并不荒唐,他们说有爱就有方向......” Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干! Orez的羊狼圈可以看作一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆。可是Drake很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已。所以Orez决定在羊狼圈中再加入一些篱笆,还是要将羊狼分开来养。 通过仔细观察,Orez发现狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变得非常暴躁,不利于他们的成长。 Orez想要添加篱笆的尽可能的短。当然这个篱笆首先得保证不能改变狼羊的所属领地,再就是篱笆必须修筑完整,也就是说必须修建在单位格子的边界上并且不能只修建一部分。

输入输出格式

输入格式:

文件的第一行包含两个整数n和m。接下来n行每行m个整数,1表示该格子属于狼的领地,2表示属于羊的领地,0表示该格子不是任何一只动物的领地。

输出格式:

文件中仅包含一个整数ans,代表篱笆的最短长度。

输入输出样例

输入样例#1: 复制
2 2
2 2 
1 1 
输出样例#1: 复制
2

说明

数据范围

10%的数据 n,m≤3

30%的数据 n,m≤20

100%的数据 n,m≤100

最小割的模型

一开始傻逼了。。上来就把正解否定了。。

源点向狼连边

狼向羊连边(狼吃羊hhh)

羊向汇点连边

空地之间互相连边

狼向空地连边

空地向羊连边

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=200001,INF=2*1e9+10;
inline char nc()
{
    static char buf[MAXN],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
    char c=nc();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=nc();}
    return x*f;
}
int S=0,T=301;
struct node
{
    int u,v,flow,nxt;
}edge[MAXN*20];
int head[MAXN],cur[MAXN],num=0;
inline void add_edge(int x,int y,int z)
{
    edge[num].u=x;
    edge[num].v=y;
    edge[num].flow=z;
    edge[num].nxt=head[x];
    head[x]=num++;
}
inline void AddEdge(int x,int y,int z) 
{
    add_edge(x,y,z);
    add_edge(y,x,0);
}int deep[MAXN];
inline bool BFS()
{
    memset(deep,0,sizeof(deep));
    deep[S]=1;
    queue<int>q;
    q.push(S);
    while(q.size()!=0)
    {
        int p=q.front();
        q.pop();
        for(int i=head[p];i!=-1;i=edge[i].nxt)
            if(!deep[edge[i].v]&&edge[i].flow)
            {
                deep[edge[i].v]=deep[p]+1;q.push(edge[i].v);
                if(edge[i].v==T) return 1;
            }
    }
    return deep[T];
}
int DFS(int now,int nowflow)
{
    if(now==T||nowflow<=0)    return nowflow;
    int totflow=0;
    for(int &i=cur[now];i!=-1;i=edge[i].nxt) 
    {
        if(deep[edge[i].v]==deep[now]+1&&edge[i].flow)
        {
            int canflow=DFS(edge[i].v,min(nowflow,edge[i].flow));
            edge[i].flow-=canflow;edge[i^1].flow+=canflow;
            totflow+=canflow;
            nowflow-=canflow;
            if(nowflow<=0) break;
        }
    }
    return totflow;
}
int Dinic()
{
    int ans=0;
    while(BFS())
    {
        memcpy(cur,head,sizeof(head)); 
        ans+=DFS(S,INF);
    }
    return ans;
}
int xx[6]={0,-1,+1,0,0},yy[6]={0,0,0,-1,+1};
int a[1001][1001],belong[1001][1001];
int N,M;
int main()
{
    #ifdef WIN32
    freopen("a.in","r",stdin);
    #else
    #endif
    memset(head,-1,sizeof(head));
    N=read();M=read();T=N*M+2;
       for(int i=1;i<=N;i++)
        for(int j=1;j<=M;j++)
            a[i][j]=read(),belong[i][j]=(i-1)*M + j;
    for(int i=1;i<=N;i++)
        for(int j=1;j<=M;j++)
        {
            if(a[i][j]==1) 
            {
                AddEdge(S,belong[i][j],INF);
                for(int k=1;k<=4;k++)
                    if( i+xx[k] >= 1 && i+xx[k] <= N && j+yy[k] >= 1 && j+yy[k]<=M && a[i][j] != a[i+xx[k]][j+yy[k]])
                        AddEdge(belong[i][j],belong[i+xx[k]][j+yy[k]],1);
            }
            else if(a[i][j]==2) 
            {
                AddEdge(belong[i][j],T,INF);
                for(int k=1;k<=4;k++)
                    if( i+xx[k] >= 1 && i+xx[k] <= N && j+yy[k] >= 1 && j+yy[k]<=M && a[i+xx[k]][j+yy[k]] == 0 )
                        AddEdge(belong[i+xx[k]][j+yy[k]],belong[i][j],1);
            }
            else
            {
                for(int k=1;k<=4;k++)
                    if( i+xx[k] >= 1 && i+xx[k] <= N && j+yy[k] >= 1 && j+yy[k]<=M && a[i+xx[k]][j+yy[k]] == 0)
                        AddEdge(belong[i][j],belong[i+xx[k]][j+yy[k]],1);
            }
        }
    printf("%d",Dinic());
    return  0;
}
原文地址:https://www.cnblogs.com/zwfymqz/p/8410053.html