暑假集训8.10—网络流(黑白染色法)

题目:dtoj1246方格取数问题,dtoj1261骑士共存问题

    这些题目都是一个思路拉,如果把整个方盘间隔着黑白染色,同色之间不会互相影响,所以可以把两个颜色分别连在 $s$ 和 $t$ 上,中间相连的边表示两者的关系,常常是总的收益减去最小割的收益是答案要求的最大收益拉~

放个方格取数的代码吧!

#include<bits/stdc++.h>
#define _(d) while(d(isdigit(ch=getchar())))
#define il inline
using namespace std;
const int N=3510,M=20010,inf=1e9;queue<int> q;
int n,m,head[N],ne[M],to[M],v[M],d[N],ans,res,cnt=1,s,t;
int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch-48;_()x=x*10+ch-48;return f*x;}
il void insert(int x,int y,int z){ne[++cnt]=head[x];head[x]=cnt;to[cnt]=y;v[cnt]=z;}
il void add(int u,int v,int w){insert(u,v,w);insert(v,u,0);}
il bool pd(int x,int y){if(x>0&&x<=m&&y>0&&y<=n)return 1;return 0;}
il void link(int x,int y){
    if(pd(x+1,y))add(x*n+y,(x+1)*n+y,inf);if(pd(x,y+1))add(x*n+y,x*n+y+1,inf);
    if(pd(x-1,y))add(x*n+y,(x-1)*n+y,inf);if(pd(x,y-1))add(x*n+y,x*n+y-1,inf);
}
il bool bfs(){
    memset(d,-1,sizeof(d));q.push(s);d[s]=1;
    while(!q.empty()){
        int x=q.front();q.pop();
        for(int i=head[x];i;i=ne[i]){
            if(!v[i]||d[to[i]]!=-1)continue;
            q.push(to[i]);d[to[i]]=d[x]+1;
        }
    }
    return d[t]!=-1;
}
int dfs(int x,int f){
    if(x==t)return f;int w,used=0;
    for(int i=head[x];i;i=ne[i]){
        if(d[x]+1!=d[to[i]]||(!v[i]))continue;
        w=f-used;w=dfs(to[i],min(w,v[i]));
        v[i]-=w;v[i^1]+=w;used+=w;if(used==f)return used;
    }
    if(!used)d[x]=-1;return used;
}
il void dinic(){while(bfs()){res+=dfs(s,inf);}}
int main()
{
  m=read();n=read();t=n*m+n+m+1;for(int i=1;i<=m;i++)for(int j=1;j<=n;j++){
    int w=read();if((i+j)&1)add(i*n+j,t,w);else add(s,i*n+j,w),link(i,j);ans+=w;
  }
  dinic();ans-=res;printf("%d\n",ans);
  return 0;
}
View Code

 

posted @ 2018-08-12 16:42  Jessiejzy  阅读(725)  评论(0编辑  收藏  举报