[bzoj1066] [SCOI2007]蜥蜴

一道比较裸的网络流...

还在建图,就惨遭ditoly爆D:"这么裸的题,还要做啊?"

---------分割线

每一个点拆3个点,表示跳出去的时候的高度,然后每个点再拆两个点,中间连1的边,表示只能有一只蜥蜴从这个点跳出去....

然后就没啦。

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define S 0
#define T 20001
#define INF 2000000000
using namespace std;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
int n,m,d,cnt=1,ans=0;
char st[55],s[55][55];
int num[2][5][2506];
int dis[4][20][2];
int q[20005];
struct edge{
    int to,next,w;
}e[8000005];
int head[20005];
queue<int> qu;

inline int abs(int x) {return x<0?-x:x;}

void INS(int f,int t,int w)
{
    e[++cnt].next=head[f];head[f]=cnt;
    e[cnt].to=t;e[cnt].w=w;
}

void ins(int f,int k,int t,int k2,int w)
{
    //cout<<"ins"<<f<<" "<<k<<" "<<t<<" "<<k2<<" "<<w<<endl;
    int x1=(f!=S)?num[1][k][f]:S;
    int x2=(t!=T)?num[0][k2][t]:T;
    INS(x1,x2,w);
    INS(x2,x1,0);
}

void init()
{
    int cc=0;
    for(int i=0;i<2;i++)
        for(int j=0;j<4;j++)
            for(int k=1;k<=2500;k++)
                num[i][j][k]=++cc;
}

int dfs(int x,int f)
{
    if(x==T) return f;
    int used=0;
    for(int i=head[x];i;i=e[i].next)
        if(e[i].w&&q[e[i].to]==q[x]+1)
        {
            int w=dfs(e[i].to,min(e[i].w,f-used));
            e[i].w-=w;
            used+=w;
            e[i^1].w+=w;
            if(used==f) return f;
        }
    if(!used) q[x]=-1;
    return used;
}

bool bfs()
{
    memset(q,0,sizeof(q));
    q[S]=1;qu.push(S);
    while(!qu.empty())
    {
        int x=qu.front();qu.pop();
        for(int i=head[x];i;i=e[i].next)
            if(e[i].w&&!q[e[i].to])    
            {
                q[e[i].to]=q[x]+1;
                qu.push(e[i].to);    
            }
    }
    return q[T]!=0;
}

int main()
{
    n=read();m=read();d=read();init();
    for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
    for(int i=1;i<=2500;i++) for(int k=0;k<4;k++)
    {INS(num[0][k][i],num[1][k][i],1);INS(num[1][k][i],num[1][k][i],0);}
    for(int i=1;i<=n;i++) 
        for(int j=1;j<=m;j++)
        {
            for(int k=max(1,i-d);k<=min(i+d,n);k++)
                for(int l=max(1,j-d+abs(k-i));l<=min(m,j+d-abs(k-i));l++)
                    if(k!=i||l!=j)
                    for(int q=0;q<s[i][j]-'0';q++)
                        for(int p=0;p<s[k][l]-'0';p++)
                            ins((i-1)*m+j,q,(k-1)*m+l,p,1);
            if(i<=d||i+d>n||j<=d||j+d>m) 
            for(int k=0;k<s[i][j]-'0';k++) ins((i-1)*m+j,k,T,0,1);
        }
    for(int i=1;i<=n;i++)
    {
        scanf("%s",st+1);
        for(int j=1;j<=m;j++)
            if(st[j]!='.')
               ins(S,0,(i-1)*m+j,s[i][j]-'0'-1,1),ans++;
    }    
    while(bfs()) ans-=dfs(S,INF);
    cout<<ans;
    return 0;
}

 

posted @ 2017-02-28 19:50  FallDream  阅读(184)  评论(0编辑  收藏  举报