Pleasant sheep and big big wolf(最小割 最大流)

原题: http://acm.hdu.edu.cn/showproblem.php?pid=3046

题意:

n*m网格,有些块有1(羊),有些有2(狼),问最少多少块1长度的板子,隔开所有的1和2(任意一个1不能达到任意一个2)

解析:

将边界视为两个块之间的一条边,就变成了网络流问题。现在求的最小割,使到达汇点的流量为0,根据定理,最小割最大流,直接求最大流即可

每两个格子之间连1,源点到羊inf,狼到汇点inf

#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;

const int inf=0x3f3f3f3f;
const int N=40500,M=405000;

int head[N],nex[M],to[M],val[M],now;
void add(int a,int b,int v){
    to[++now]=b;val[now]=v;nex[now]=head[a];head[a]=now;
    to[++now]=a;val[now]=0;nex[now]=head[b];head[b]=now;
}

//*********************

int sp,ep,d[N];

int bfs(){
    queue<int>Q;
    memset(d,-1,sizeof(d));
    d[sp]=0;
    Q.push(sp);
    while(!Q.empty()){
        int p=Q.front();Q.pop();
        for(int i=head[p];~i;i=nex[i]){
            int u=to[i];
            if(d[u]==-1&&val[i]>0){
                d[u]=d[p]+1;
                Q.push(u);
            }
        }
    }
    return d[ep]!=-1;
}

int dfs(int p,int v){
    int r=0;
    if(p==ep)return v;
    for(int i=head[p];(~i)&&r<v;i=nex[i]){
        int u=to[i];
        if(val[i]>0&&d[u]==d[p]+1){
            int x=dfs(u,min(val[i],v-r));
            r+=x;
            val[i]-=x;
            val[i^1]+=x;
        }
    }
    if(!r)d[p]=-2;
    return r;
}

int dinic(){
    int ans=0,t;
    while(bfs()){
        while(t=dfs(sp,inf))ans+=t;
    }
    return ans;
}

//***********************

void init(){
    now=-1;//要求第一条边为0
    memset(head,-1,sizeof(head));
}

int n,m;
int Mp[201][201];
int id(int i,int j){return (i-1)*201+j;}

int di[4][2]={{0,1},{1,0},{-1,0},{0,-1}};

int main(){int ca=0;while(cin>>n>>m){
    init();
    sp=0;ep=40400;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%d",&Mp[i][j]);
            for(int k=0;k<4;k++){
                int x=i+di[k][0],y=j+di[k][1];
                if(x<1||y<1||x>n||y>m)continue;
                add(id(i,j),id(x,y),1);
            }
            if(Mp[i][j]==1){
                add(id(i,j),40400,inf);
            }
            if(Mp[i][j]==2){
                add(0,id(i,j),inf);
            }
        }
    }
    int ans=dinic();
    printf("Case %d:\n%d\n",++ca,ans);
}}


猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/86596039