bzoj1412 [ZJOI2009]狼和羊的故事

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;
}
博主是蒟蒻,有问题请指出,谢谢!
本博客中博文均为原创,未经博主允许请勿随意转载,谢谢。
posted @ 2017-10-03 15:39  菜狗xzz  阅读(207)  评论(2编辑  收藏  举报