BZOJ 1412: [ZJOI2009]狼和羊的故事【最小割】

1412: [ZJOI2009]狼和羊的故事

【题目描述】
传送门

【题解】

典型的最小割,那么怎么建图呢?
首先肯定要建超级源和汇,然后肯定狼向羊建边(反过来也可以),若有空的的话就是(狼->空->空->羊)按照这个顺序建边就可以了。

代码如下

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int flg[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int hd,tl,n,m,a[105][105],S,T,dep[10005],que[10005];
int tot=-1,lnk[10005],nxt[2*40005],son[2*40005],W[2*40005];
void add(int x,int y,int w){son[++tot]=y;nxt[tot]=lnk[x];lnk[x]=tot;W[tot]=w;}
int CHG(int x,int y){return (x-1)*m+y;}
bool check(int x,int y){if(x<1||x>n||y<1||y>m) return 0;return 1;}
bool BFS(){
    memset(dep,0,sizeof(dep));dep[S]=1;
    hd=0,que[tl=1]=S;
    while(hd!=tl){
        int x=que[++hd];
        for(int j=lnk[x];j^-1;j=nxt[j])
        if(!dep[son[j]]&&W[j]>0) dep[son[j]]=dep[x]+1,que[++tl]=son[j];
    }
    return dep[T];
}
int DFS(int x,int flow){
    if(x==T) return flow;
    int now=0;
    for(int j=lnk[x];j^-1;j=nxt[j])
    if((dep[son[j]]==dep[x]+1)&&W[j]>0){
        int y=DFS(son[j],min(flow,W[j]));
        if(y>0){W[j]-=y;W[j^1]+=y;now+=y;if(now==flow) return flow;}
    }
    if(!now) dep[x]=0;
    return now;
}
int Dinic(){
    int ans=0;
    while(BFS())
    while(int t=DFS(S,1e9)) ans+=t;
    return ans;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("prob.in","r",stdin);
    freopen("prob.out","w",stdout);
    #endif
    scanf("%d%d",&n,&m);S=0,T=n*m+1; 
    memset(lnk,-1,sizeof(lnk));
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++){
        scanf("%d",&a[i][j]);
        if(a[i][j]==2) add(S,CHG(i,j),1e9),add(CHG(i,j),S,0);
        if(a[i][j]==1) add(CHG(i,j),T,1e9),add(T,CHG(i,j),0);
    }
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    for(int k=0;k<4;k++)
    if(check(i+flg[k][0],j+flg[k][1])){
        if(a[i][j]==2&&a[i+flg[k][0]][j+flg[k][1]]==1)
        add(CHG(i,j),CHG(i+flg[k][0],j+flg[k][1]),1),add(CHG(i+flg[k][0],j+flg[k][1]),CHG(i,j),0);
        if(a[i][j]==2&&a[i+flg[k][0]][j+flg[k][1]]==0)
        add(CHG(i,j),CHG(i+flg[k][0],j+flg[k][1]),1),add(CHG(i+flg[k][0],j+flg[k][1]),CHG(i,j),0);
        if(a[i][j]==0&&a[i+flg[k][0]][j+flg[k][1]]==0)
        add(CHG(i,j),CHG(i+flg[k][0],j+flg[k][1]),1),add(CHG(i+flg[k][0],j+flg[k][1]),CHG(i,j),0);
        if(a[i][j]==0&&a[i+flg[k][0]][j+flg[k][1]]==1)
        add(CHG(i,j),CHG(i+flg[k][0],j+flg[k][1]),1),add(CHG(i+flg[k][0],j+flg[k][1]),CHG(i,j),0);
    }

    printf("%d\n",Dinic());
    return 0;
}
posted @ 2018-06-10 16:06  XSamsara  阅读(149)  评论(0编辑  收藏  举报