1613 跑路
这道题一说跑的步数是2k立刻就懂了,倍增
这道题分三步进行解答:
1.建图,这个步骤就是初始化,输入起点终点dis数组存储可以1秒达到,然后g[x][y][k]存的是x~y之间是不是存在一条2k的路径,所以我们得进行标记
2.预处理这个步骤其实就是说将那些可以一秒达到的地方链接一下然后把距离设置成一秒也就是标记,然后做下面的操作
3.最短路这些步骤一秒到达的地方直接跑一边最短路,也就是Floyd,小于50的数据floyd可以承受
最后这道题就做出来了,不难想,挺好实现的
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
int dis[60][60];//路径changdu
int n,m;
bool g[60][60][70];//判断是否存在
void init()
{
memset(g,0,sizeof(g));
memset(dis,10,sizeof(dis));
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
dis[x][y]=1;
g[x][y][0]=1;
}
}
void work()
{
for(int k=1;k<=64;k++)
//枚举步数
for(int i=1;i<=n;i++)
for(int t=1;t<=n;t++)
for(int j=1;j<=n;j++)
//枚举三个点
if(g[i][t][k-1]&&g[t][j][k-1])
//说明i~j可以到达
{
g[i][j][k]=true;
//标记从i到j存在一条长度为2^k的路径
dis[i][j]=1;
//i到j距离可以一秒到达
}
}
void floyd()
{
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);//松弛,求最小值
}
int main()
{
init();
work();
floyd();
cout<<dis[1][n]<<endl;
return 0;
}