码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj1412

时间:2018-06-20 19:08:49      阅读:214      评论:0      收藏:0      [点我收藏+]

标签:span   while   dep   dfs   queue   http   getch   memset   def   

从狼向空格或羊剪边,从空格向空格或羊建边,最大流最小割

最大流dinic打法(这里用了当前弧优化)

diniv当前弧优化讲解

 

#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#define maxn 10002
#define inf 0x3ffffff
using namespace std;
int n,m,ans,S,T,cnt,cur[maxn],dep[maxn],head[maxn],nex[maxn<<4],to[maxn<<4],w[maxn<<4],s[102][102];
int bzx[]={0,1,0,-1},bzy[]={1,0,-1,0};
inline void read(int &x){
    char ch=getchar();x=0;int f=1;
    while(!isdigit(ch)){if(ch==-)f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-0;ch=getchar();}
    x*=f;
}
inline void addedge(int u,int v,int wi){nex[cnt]=head[u];to[cnt]=v;w[cnt]=wi;head[u]=cnt++;nex[cnt]=head[v];to[cnt]=u;w[cnt]=0;head[v]=cnt++;}
inline int bfs(){
    queue<int>q;while(!q.empty())q.pop();
    memset(dep,0,sizeof dep);dep[S]=1;q.push(S);
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=head[u];~i;i=nex[i]){
            int v=to[i];
            if(w[i]>0 && dep[v]==0){
                dep[v]=dep[u]+1;
                q.push(v);
            }
        }
    }
    return dep[T]!=0;
}
inline int dfs(int u,int flow){
    if(u==T)return flow;
    int ans=0,x=0;
    for(int &i=cur[u];~i;i=nex[i]){
        int v=to[i];
        if(w[i]>0 && dep[v]==dep[u]+1){
            x=dfs(v,min(flow-ans,w[i]));
            w[i]-=x;w[i^1]+=x;
            ans+=x;
            if(ans==flow)return flow;
        }
    }
    if(ans==0)dep[u]=0;
    return ans;
}
inline void dinic(){
    while(bfs()){
        for(int i=S;i<=T;i++)cur[i]=head[i];ans+=dfs(S,inf);
    }
}
int main(){
    memset(head,-1,sizeof head);
    read(n);read(m);S=0;T=n*m+1;
    for(int i=1;i<=n;i++)s[i][0]=s[i][m+1]=-1;
    for(int i=1;i<=m;i++)s[0][i]=s[n+1][i]=-1;
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){
        read(s[i][j]);
        if(s[i][j]==2)addedge(S,(i-1)*m+j,inf);if(s[i][j]==1)addedge((i-1)*m+j,T,inf);
    }
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)for(int k=0;k<4;k++){
        if((s[i][j]==2 ||s[i][j]==0) && (s[i+bzx[k]][j+bzy[k]]==1 || s[i+bzx[k]][j+bzy[k]]==0))addedge((i-1)*m+j,(i+bzx[k]-1)*m+j+bzy[k],1);
    }
    dinic();
    printf("%d",ans);
    return 0;
}

 

bzoj1412

标签:span   while   dep   dfs   queue   http   getch   memset   def   

原文地址:https://www.cnblogs.com/MikuKnight/p/9204684.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!