codevs1907 方格取数 3||tyvj1338QQ农场|网络流

来源:互联网 发布:万顺天国知乎 编辑:程序博客网 时间:2024/05/21 10:39

自己做出来的第一道最小割的题 

我是不是太弱了QAQ

题解:

把矛盾的点分为两排

然后随便连连边就好了

#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<queue>#include<vector>#include<set>#include<map>#include<algorithm>#include<iostream>#define T 400040#define mx 122222222using namespace std;int sc(){int i=0; char c=getchar();while(c>'9'||c<'0')c=getchar();while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();return i;}int dis[T],q[T];int id[202][202],col[202][202],v[202][202];int head[T],nxt[T*16],lst[T*16],c[T*16];int cnt,n,m,ans,sum,tot=1;int S,E;void add(int x,int y,int z){if(!x||!y)return;lst[++tot]=y;c[tot]=z;nxt[tot]=head[x];head[x]=tot;}void insert(int x,int y,int z){add(x,y,z);add(y,x,0);}bool bfs(){for(int i=1;i<=E;i++)dis[i]=0;dis[S]=1;int l=1,r=2; q[1]=S;while(l<r){int x=q[l++];for(int i=head[x];i;i=nxt[i])    if(c[i]&&!dis[lst[i]])    {    dis[lst[i]]=dis[x]+1;    q[r++]=lst[i];    }}return dis[E];}int dfs(int x,int f){if(x==E)return f;int ww=0,w;for(int i=head[x];i;i=nxt[i])    if(c[i]&&dis[lst[i]]==dis[x]+1)    {    w=dfs(lst[i],min(f-ww,c[i]));    ww+=w;c[i]-=w,c[i^1]+=w;    if(ww==f)return ww;    }if(ww==0)dis[x]=0;return ww;}int main(){n=sc();m=sc();for(int i=1;i<=n;i++)    for(int j=1;j<=m;j++){id[i][j]=++cnt,v[i][j]=sc(),sum+=v[i][j];col[i][j]=i+j&1;}S=n*m+1,E=S+1;    for(int i=1;i<=n;i++)    for(int j=1;j<=m;j++)    {    if(col[i][j]){insert(S,id[i][j],v[i][j]);insert(id[i][j],id[i-1][j],mx);insert(id[i][j],id[i][j-1],mx);        insert(id[i][j],id[i][j+1],mx);insert(id[i][j],id[i+1][j],mx);        }    else  insert(id[i][j],E,v[i][j]);    }while(bfs()) sum-=dfs(S,mx);cout << sum;return 0;}


0 0
原创粉丝点击