洛谷 P1606 [USACO07FEB]荷叶塘Lilypad Pond【spfa】

和bzoj同名题不一样!
起点和水点向花费一个荷花能到的第一个点连一条边权为1的有向边,然后跑计数spfa即可

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int N=35,dx[]={-1,-1,1,1,-2,-2,2,2},dy[]={-2,2,-2,2,-1,1,-1,1};
int n,m,a[N][N],id[N][N],tot,h[N*N],cnt,s,t,dis[N*N],vis[N][N],ti;
long long b[N*N];
bool v[N*N];
struct qwe
{
    int ne,to;
}e[500005];
void add(int u,int v)
{//cerr<<u<<" "<<v<<endl;
    cnt++;
    e[cnt].ne=h[u];
    e[cnt].to=v;
    h[u]=cnt;
}
inline bool ok(int x,int y)
{
    return x>=1&&x<=n&&y>=1&&y<=m&&a[x][y]!=2&&vis[x][y]!=ti;
}
void dfs(int u,int x,int y,int f)
{//cerr<<u<<"  "<<x<<" "<<y<<endl;
    vis[x][y]=ti;
    if((a[x][y]==4||a[x][y]==0)&&!f)
    {
        add(u,id[x][y]);
        // add(id[x][y],u);
        return;
    }
    for(int i=0;i<8;i++)
        if(ok(x+dx[i],y+dy[i]))
            dfs(u,x+dx[i],y+dy[i],0);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            scanf("%d",&a[i][j]);
            id[i][j]=++tot;
            if(a[i][j]==3)
                s=id[i][j];
            if(a[i][j]==4)
                t=id[i][j];
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(a[i][j]!=2&&a[i][j]!=1)
                ti++,dfs(id[i][j],i,j,1);
    queue<int>q;
    for(int i=1;i<=tot;i++)
        dis[i]=1e9;
    dis[s]=0;
    b[s]=1;
    v[s]=1;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        v[u]=0;
        for(int i=h[u];i;i=e[i].ne)
        {
            if(dis[e[i].to]>dis[u]+1)
            {
                dis[e[i].to]=dis[u]+1;
                b[e[i].to]=b[u];
                if(!v[e[i].to])
                {
                    v[e[i].to]=1;
                    q.push(e[i].to);
                }
            }
            else if(dis[e[i].to]==dis[u]+1)
            {
                b[e[i].to]+=b[u];
                if(!v[e[i].to])
                {
                    v[e[i].to]=1;
                    q.push(e[i].to);
                }
            }
        }
    }
    if(dis[t]==1e9)
        puts("-1");
    else
        printf("%d\n%lld\n",dis[t]-1,b[t]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lokiii/p/9571012.html