题意
思考
跑最短路再判定肯定是错的,我们可以这样做:用 \(f[i][j][k]\) 表示 \(i\) 是否能用 \(2^k\) 步到达 \(j\),能到达为 \(1\), 不能到达为 \(0\), 跑一遍\(floyd\)来传递,将能用 \(2^k\) 步到达的两点间边权设为 \(1\),最后跑一遍最短路即可
代码
#include<bits/stdc++.h>
using namespace std;
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x * f;
}
const int N = 110;
int mp[N][N], f[N][N][N], n, m;
void init(){
for(int p=1; p<=64; p++){
for(int k=1; k<=n; k++){
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
if(f[i][k][p-1] && f[k][j][p-1]){
f[i][j][p] = 1; mp[i][j] = 1;
}
}
}
}
}
for(int k=1; k<=n; k++){
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
if(mp[i][k] + mp[k][j] < mp[i][j]){
mp[i][j] = mp[i][k] + mp[k][j];
}
}
}
}
}
int main(){
n = read(), m = read();
memset(mp, 0x3f, sizeof(mp));
for(int i=1; i<=m; i++){
int u = read(), v = read();
mp[u][v] = 1; f[u][v][0] = 1;
}
init();
cout << mp[1][n];
return 0;
}