Luogu P1613 跑路
非常神仙的倍增题目
g[i][j][k]
表示点\(i\)到点\(j\)之间是否存在一条长度为\(2^k\)的路径
dis[i][j]
表示点\(i\)到点\(j\)之间需要用几次跑路机
代码应该不难理解
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;
LL read() {
LL k = 0, f = 1; char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9')
k = k * 10 + c - 48, c = getchar();
return k * f;
}
int dis[51][51]; bool g[51][51][51];
int main() {
int n = read(), m = read();
memset(dis, 127/3, sizeof(dis));
for(int i = 1; i <= m; ++i) {
int x = read(), y = read();
dis[x][y] = 1; g[x][y][0] = 1;
}
for(int o = 1; o <= 31; ++o)
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
for(int k = 1; k <= n; ++k)
if(g[i][k][o-1] && g[k][j][o-1])
g[i][j][o] = 1, dis[i][j] = 1;
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]);
cout << dis[1][n] << endl;
return 0;
}