自己做出来的第一道最小割的题
我是不是太弱了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 122222222
using 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;
}