bzoj 1412: [ZJOI2009]狼和羊的故事

http://www.lydsy.com/JudgeOnline/problem.php?id=1412

 

超级源点连向所有的狼,超级汇点连向所有羊,流量为INF

相邻连边流量为1,最小割

#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
std::queue<int>que;
int fs[5]={0,1,0,-1,0};
#define INF 0x7fffffff
const int maxn = 300007;
int map[1007][1007];
inline int read() {
    int x=0;
    char c=getchar();
    while(c<'0'||c>'9')c=getchar();
    while(c<='9'&&c>='0')x=x*10+c-'0',c=getchar();
    return x;
}
int n,m,S,T,src,decc;
struct node{
    int v,next,flow;
}edge[maxn];int head[maxn],num=1,cur[maxn],lev[maxn];
void add_edge(int u,int v,int w) {
    edge[++num].v=v;edge[num].next=head[u];head[u]=num;
    edge[num].flow=w;
}
bool bfs() {
    while(!que.empty()) que.pop();
    std::memset(lev,-1,sizeof lev);
    memcpy(cur,head,sizeof head);  
    lev[src]=0;
    que.push(src);int now;
    while(!que.empty()) {
        now=que.front();que.pop();
        for(int i=head[now];i;i=edge[i].next) {
            int v=edge[i].v;
            if(lev[v]==-1&&edge[i].flow>0) {
                lev[v]=lev[now]+1;
                if(v==decc)return true;
                que.push(v);
            }
        }
    }
    return false;
}
int dfs(int now,int flow) {
    if(now==decc)return flow;
    int rest=0,delta;
    for(int &i=cur[now];i;i=edge[i].next) {
        int v=edge[i].v;
        if(lev[v]==lev[now]+1&&edge[i].flow>0) {
            delta=dfs(v,std::min(flow-rest,edge[i].flow));
            if(delta) {
                edge[i].flow-=delta;
                edge[i^1].flow+=delta;
                rest+=delta;if(rest==flow)break;
            }
        }
    }
    if(rest==flow)lev[now]=-1;//满流
    return rest;
}
int Dinic() {
    int ans=0;
    while(bfs()) 
        ans+=dfs(src,INF);
    return ans;
}
inline void add(int a,int b,int flow) {
    add_edge(a,b,flow);add_edge(b,a,0);
}
inline int calc(int i,int j) {
    return (i-1)*m+j;    
}
int main() {
    n=read(),m=read();
    src=0;decc=n*m+1;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            map[i][j]=read();
    for(int i=1;i<=n;++i) {
        for(int j=1;j<=m;++j) {
            if(map[i][j]==1)add(src,calc(i,j),INF);
            else if(map[i][j]==2){ add(calc(i,j),decc,INF);continue;}
            for(int k=0;k<4;++k) {
                int x=i+fs[k],y=j+fs[k+1];
                if(x<=0||x>n||y<=0||y>m)continue;
                add(calc(i,j),calc(x,y),1);
            }
        }
    }
    printf("%d\n",Dinic());
    return 0;
}
    

 

posted @ 2017-12-23 20:16  zzzzx  阅读(172)  评论(0编辑  收藏  举报