AC日记——[ZJOI2009]狼和羊的故事 bzoj 1412

1412

 

思路:

  最小割;

  狼作为一个点集a,空领地作为点集b,羊作为点集c;

  s向a连边,c向t连边,a向b连边,b向b连边,b向c连边;

  如何理解最小割?

  a,c之间割掉最少的路径(栅栏)使其没有通路;

 

来,上代码:

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

#define maxn 20005
#define maxm 200005
#define INF 0x7ffffff

const int dx[5]={0,-1,0,1,0};
const int dy[5]={0,0,1,0,-1};

int s,t,cnt=1,size,que[maxm],deep[maxn],n,m;
int head[maxn],E[maxm],V[maxm],F[maxm],map[105][105];

inline void edge_add(int u,int v,int f)
{
    E[++cnt]=head[u],V[cnt]=v,F[cnt]=f,head[u]=cnt;
    E[++cnt]=head[v],V[cnt]=u,F[cnt]=0,head[v]=cnt;
}

bool bfs()
{
    for(int i=s;i<=t;i++) deep[i]=-1;
    int h=0,tail=1;que[h]=s,deep[s]=0;
    while(h<tail)
    {
        int now=que[h++];
        for(int i=head[now];i;i=E[i])
        {
            if(deep[V[i]]<0&&F[i]>0)
            {
                deep[V[i]]=deep[now]+1;
                if(V[i]==t) return true;
                que[tail++]=V[i];
            }
        }
    }
    return false;
}

int flowing(int now,int flow)
{
    if(now==t||flow<=0) return flow;
    int oldflow=0;
    for(int i=head[now];i;i=E[i])
    {
        if(deep[V[i]]==deep[now]+1&&F[i]>0)
        {
            int pos=flowing(V[i],min(flow,F[i]));
            F[i]-=pos,F[i^1]+=pos;
            flow-=pos,oldflow+=pos;
            if(flow==0) return oldflow;
        }
    }
    if(oldflow==0) deep[now]=-1;
    return oldflow;
}

int main()
{
    scanf("%d%d",&n,&m);
    size=n*m,t=size+1;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++) scanf("%d",&map[i][j]);
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(map[i][j]==1) edge_add(s,(i-1)*m+j,INF);
            if(map[i][j]==2) edge_add((i-1)*m+j,t,INF);
            for(int v=1;v<=4;v++)
            {
                int xx=i+dx[v],yy=j+dy[v];
                if(xx>0&&xx<=n&&yy>0&&yy<=m)
                {
                    if(map[i][j]!=1||map[xx][yy]!=1) edge_add((i-1)*m+j,(xx-1)*m+yy,1);
                }
            }
        }
    }
    int ans=0;
    while(bfs()) ans+=flowing(s,INF);
    cout<<ans;
    return 0;
}

 

posted @ 2017-04-15 10:26  IIIIIIIIIU  阅读(207)  评论(0编辑  收藏  举报