[BZOJ 1412] 狼与羊的故事

Link:

BZOJ 1412 传送门

Solution:

非常明显的最小割模型:

将所有点分成两个互不相邻的点集,且要求代价最小

 

建图:

$<S,sheep,INF>$

$<wolf,T,INF>$

$<sheep,wolf/ground,1>$、$<ground,wolf/sheep/ground,1>$

Code:

#include <bits/stdc++.h>

using namespace std;
const int MAXN=10005,MAXM=40005,INF=1<<27;
namespace Max_Flow
{
    int head[MAXN],S,T,level[MAXN],iter[MAXN],tot=-1;
    struct edge{int nxt,to,cap;}e[MAXM<<2];
    
    void add_edge(int from,int to,int cap)
    {
        e[++tot].nxt=head[from];e[tot].to=to;e[tot].cap=cap;head[from]=tot;
        e[++tot].nxt=head[to];e[tot].to=from;e[tot].cap=0;head[to]=tot;
    }    
    bool bfs()
    {
        memset(level,-1,sizeof(level));
        queue<int> q;q.push(S);level[S]=0;
        while(!q.empty())
        {
            int u=q.front();q.pop();
            for(int i=head[u];i!=-1;i=e[i].nxt)
                if(e[i].cap && level[e[i].to]==-1)
                    level[e[i].to]=level[u]+1,q.push(e[i].to);
        }
        return (level[T]!=-1);
    }    
    int dfs(int v,int f)
    {
        if(v==T) return f;
        int ret=0;
        for(int &i=iter[v];i!=-1;i=e[i].nxt)
        {
            if(level[e[i].to]==level[v]+1 && e[i].cap)
            {
                int d=dfs(e[i].to,min(f,e[i].cap));
                e[i].cap-=d;e[i^1].cap+=d;
                f-=d;ret+=d;if(!f) break;
            }
        }
        return ret;
    }    
    int Dinic()
    {
        int ret=0;
        while(bfs())
        {
            for(int i=0;i<MAXN;i++) iter[i]=head[i];
            ret+=dfs(S,INF);
        }
        return ret;
    }
}

int dx[]={1,-1,0,0},dy[]={0,0,1,-1};
int n,m,dat[105][105];

int main()
{
    using namespace Max_Flow;
    S=0;T=10001;memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&dat[i][j]);
    
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(dat[i][j]==1) add_edge(S,(i-1)*m+j,INF);
            if(dat[i][j]==2){add_edge((i-1)*m+j,T,INF);continue;}
            for(int k=0;k<4;k++)
            {
                int fx=i+dx[k],fy=j+dy[k];
                if(fx<1||fx>n||fy<1||fy>m) continue;
                if(dat[i][j]!=1 || dat[fx][fy]!=1)
                    add_edge((i-1)*m+j,(fx-1)*m+fy,1);
            }
        }
    printf("%d",Dinic());
    return 0;
}

 

posted @ 2018-06-28 11:54  NewErA  阅读(158)  评论(0编辑  收藏  举报