Luogu P1613 跑路

倍增+Floyd

首先令$g[i][j][k]$表示$i$到$j$的有没有长度为$2^{k}$的路径,1表示有,0表示没有

那么可以处理出有之间连边($u$->$v$)的两点$u$,$v$,$g[u][v][0]=1$

然后再令$f[i][j]$表示i到j经过$2^{k}$的边的个数

那么只要存在一个$k$,使得$g[i][j][k]==1$那么$f[i][j]=1$

然后以$f$数组跑Floyd处理出1-n的最短路即可

#include <bits/stdc++.h>
#define inf 1e9
using namespace std;
int n,m,g[60][60][65];
int f[60][60];
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
          f[i][j]=inf;
    }
    for (int i=1;i<=m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        g[u][v][0]=1;//同上
        f[u][v]=1;
    }
    for (int t=1;t<=64;t++)
    {
        for (int k=1;k<=n;k++)
        {
            for (int i=1;i<=n;i++)
            {
                for (int j=1;j<=n;j++)
                {
                    if (g[i][k][t-1] && g[k][j][t-1])
                    {
                        g[i][j][t]=1;
                        f[i][j]=1;
                    }
                }
            }
        }
    }
    for (int k=1;k<=n;k++)//Floyd
    {
        for (int i=1;i<=n;i++)
        {
            for (int j=1;j<=n;j++)
              f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
        }
    }
    printf("%d\n",f[1][n]);
}

 

posted @ 2019-07-18 16:08  SevenDawns  阅读(154)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end