bzoj1412 [ZJOI2009]狼和羊的故事
网络流最小割题。
hzwer:挖掘栅栏的本质:只能建在相邻两个,且建好后使得狼和羊之间不存在通路。而割的定义是:使S集和T集不存在通路。而题目又要求建的栅栏最少,于是就是最小割问题了。
rt,就是裸题。
这里说1点:我本来想缩点以优化复杂度的,后来发现是错的。。。
3 3
1 1 1
1 0 1
2 0 2
这组数据,正解3,缩点就变成4了。
然后。。。
原因就是:不缩点的话在空格处是限流的,如果缩了点就没有限流了,导致答案过大。
另外:怎么大家都没加当前弧优化。。。
// It is made by XZZ
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define il inline
#define rg register
#define vd void
typedef long long ll;
il int gi(){
rg int x=0;rg bool flg=0;rg char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')flg=1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return flg?-x:x;
}
char l[110][110];
const int maxn=10010,maxm=(100*100+100*100+100+100)<<2,S=0,T=10001;
int dep[maxn],fir[maxn],head[maxn],dis[maxm],w[maxm],nxt[maxm],id=1,n,m;
il vd _add(int a,int b,int c){nxt[++id]=head[a],head[a]=id,dis[id]=b,w[id]=c;}
il vd add(int a,int b,int c){_add(a,b,c),_add(b,a,0);}
il bool BFS(){
static int que[maxn],hd,tl;static bool vis[maxn];
memset(vis,0,sizeof vis);hd=tl=0;que[tl++]=S,vis[S]=1,dep[S]=1;
while(hd^tl){
static int x;x=que[hd];
for(int i=head[x];i;i=nxt[i])if(w[i]&&!vis[dis[i]])vis[dis[i]]=1,dep[dis[i]]=dep[x]+1,que[tl++]=dis[i];
++hd;
}return vis[T];
}
il int Dinic(int x,int maxflow){
if(x==T)return maxflow;
int flow=0,D;
for(int&i=fir[x];i;i=nxt[i])if(dep[dis[i]]==dep[x]+1&&w[i]){
D=Dinic(dis[i],min(w[i],maxflow-flow));
w[i]-=D,w[i^1]+=D,flow+=D;
if(maxflow==flow)return flow;
}return flow;
}
il int Dinic(){
int ret=0;
while(BFS())memcpy(fir,head,sizeof fir),ret+=Dinic(S,23333333);
return ret;
}
#define P(x,y) ((x-1)*m+y)
il vd Add(int x1,int y1,int x2,int y2){
char a=l[x1][y1],b=l[x2][y2];
if(a=='0'&&b=='0')add(P(x1,y1),P(x2,y2),1),add(P(x2,y2),P(x1,y1),1);
if(a==b)return;
if((a=='1')||(a=='0'&&b=='2'))add(P(x1,y1),P(x2,y2),1);
else add(P(x2,y2),P(x1,y1),1);
}
int main(){
n=gi(),m=gi();
rep(i,1,n)rep(j,1,m)do l[i][j]=getchar();while(l[i][j]>'2'||l[i][j]<'0');
rep(i,1,n)rep(j,1,m){
if(l[i][j]=='1')add(S,P(i,j),233333333);
if(l[i][j]=='2')add(P(i,j),T,233333333);
}
rep(i,2,n)Add(i,1,i-1,1);
rep(i,2,m)Add(1,i,1,i-1);
rep(i,2,n)rep(j,2,m)Add(i,j,i-1,j),Add(i,j,i,j-1);
printf("%d",Dinic());
return 0;
}