bzoj 1066: [SCOI2007] 蜥蜴

    这道题还是挺好想的,但我一开始还是想错了……

    把每个石柱拆成两个点,一个入度,一个出度,两个点连一条容量为高度的边,这样就可以限制从此石柱上经过的蜥蜴的数量。关于蜥蜴是否单独成点,我是单独当成了一个点,貌似做麻烦了,可以直接源点连石柱,但那样我想会不会造成一些问题,貌似也没有。

    虽然很水,但还是调了很久。主要问题出在建图上,我把一个点拆成了高度个点,这样无法达到上面说的限制蜥蜴经过的数量这个功能,所以WA了很久,看了题解,才突然明白,这么搞不行……

    代码如下:

#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <iostream>

#include <algorithm>

#include <queue>

#define N 25

#define inf 1<<30

using namespace std;



struct sss

{

    int x,y;

}xiyi[N*N];

int n,m,S,T,d;

int a[N][N]={0},num[N][N]={0},stonenum=0,xiyinum=0;

int p[N*N*5],next[N*N*N*N*6],v[N*N*N*N*6],f[N*N*N*N*6],bnum=-1;



bool kexing(int x,int y)

{

    if (x<1||x>n||y<1||y>m) return false;

    else return true;

}



void addbian(int x,int y,int flow)

{

    bnum++; next[bnum]=p[x];

    p[x]=bnum; v[bnum]=y; f[bnum]=flow;

    bnum++; next[bnum]=p[y];

    p[y]=bnum; v[bnum]=x; f[bnum]=0;

}



int dis[N*N*5];



bool BFS()

{

    int i,j,k;

    queue<int> q;

    for (i=1;i<=T;i++) dis[i]=-1;

    dis[S]=0; q.push(S);

    while (!q.empty())

    {

        j=q.front(); q.pop(); k=p[j];

        while (k!=-1)

        {

            if (f[k]&&dis[v[k]]==-1)

            {

                dis[v[k]]=dis[j]+1;

                q.push(v[k]);

            }

            k=next[k];

        }

    }

    if (dis[T]==-1) return false;

    else return true;

}



int DFS(int now,int change)

{

    int i,j,k,flow=0;

    if (now==T||change==0) return change;

    k=p[now];

    while (k!=-1)

    {

        if (f[k]&&dis[v[k]]==dis[now]+1&&(i=DFS(v[k],min(change,f[k])))>0)

        {

            f[k]-=i; f[k^1]+=i;

            flow+=i; change-=i;

            if (change==0) break;

        }

        k=next[k];

    }

    dis[now]=-1;

    return flow;

}



int dinic()

{

    int ans=0,flow;

    while (BFS())

        while (flow=DFS(S,inf))

            ans+=flow;

    return ans;

}



bool bianjie(int x,int y)

{

    if (x<=d||y<=d) return true;

    else if (n-x<d||m-y<d) return true;

    else return false;

}



int main()

{

    int i,j,k,x,y;

    char s[N];

    scanf("%d%d%d",&n,&m,&d);

    S=n*m*3+1; T=n*m*3+2;

    for (i=1;i<=T;i++) p[i]=-1;

    for (i=1;i<=n;i++)

    {

        scanf("%s",s);

        for (j=0;j<m;j++)

            if (s[j]!='0') a[i][j+1]=s[j]-'0';

    }

    for (i=1;i<=n;i++)

    {

        scanf("%s",s);

        for (j=0;j<m;j++)

            if (s[j]=='L')

            {

                xiyinum++; a[i][j+1]--;

                xiyi[xiyinum].x=i; xiyi[xiyinum].y=j+1;

            }

    }

    for (i=1;i<=n;i++)

        for (j=1;j<=m;j++)

            if (a[i][j]>0)

            {

                stonenum++;

                num[i][j]=stonenum;

            }

    for (i=1;i<=n;i++)

        for (j=1;j<=m;j++)

            if (a[i][j]>0)

            {

                addbian(num[i][j],num[i][j]+n*m,a[i][j]);

                if (bianjie(i,j))

                    addbian(num[i][j]+n*m,T,inf);

                for (int I=-d;I<=d;I++)

                    for (int J=-d;J<=d;J++)

                    if (!(I==0&&J==0)&& I*I+J*J<=d*d)

                    {

                        x=i+I; y=j+J;

                        if (kexing(x,y)&&a[x][y])

                            addbian(num[i][j]+n*m,num[x][y],inf);

                    }

            }

    for (i=1;i<=xiyinum;i++)

    {

        int x1=xiyi[i].x,y1=xiyi[i].y;

        addbian(S,i+n*m*2,1);

        if (bianjie(x1,y1))

            addbian(i+n*m*2,T,inf);

        for (int I=-d;I<=d;I++)

            for (int J=-d;J<=d;J++)

                if (!(I==0&&J==0)&& I*I+J*J<=d*d)

                {

                    x=x1+I; y=y1+J;

                    if (kexing(x,y)&&a[x][y])

                        addbian(i+n*m*2,num[x][y],inf);

                }

    }

    printf("%d\n",xiyinum-dinic());

}

 

你可能感兴趣的:(2007)