懒得贴题自己去看
一道倍增模板题,可以练习代码熟练度
开一个数组f[i][j][k]表示从i到j用
2k
能否到达,然后枚举中间点,如果i到mid可以用
2k−1
步到达,mid到j可以用
2k−1
步到达,那么从i到j就可以用
2k
步到达,代码如下
for(int mid=1;mid<=50;mid++)
for(int i=1;i<=50;i++)
for(int j=1;j<=50;j++)
for(int k=1;k<=50;k++)
{
if(f[i][j][mid-1]&&f[j][k][mid-1])
f[i][k][mid]=1,way[i][k]=1;
}
然后再跑一遍Floyd,轻松AC
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
bool f[51][51][51];
int way[51][51];
int main()
{
int n,m;
cin>>n>>m;
memset(way,127/3,sizeof(way));
for(int i=1;i<=m;i++)
{
int u,v;
cin>>u>>v;
way[u][v]=1;
f[u][v][0]=1;
}
for(int mid=1;mid<=50;mid++)
for(int i=1;i<=50;i++)
for(int j=1;j<=50;j++)
for(int k=1;k<=50;k++)
{
if(f[i][j][mid-1]&&f[j][k][mid-1])
f[i][k][mid]=1,way[i][k]=1;
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(i!=j&&j!=k&&k!=i)
way[i][j]=min(way[i][j],way[i][k]+way[k][j]);
}
cout<<way[1][n];
return 0;
}