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;
}
原文地址:https://www.cnblogs.com/morslin/p/11855613.html