「luogu1613」跑路

传送门
Luogu

解题思路

对于所有可以用 \(2^k\) 形式表示的 \(dis(i,j)\),将\(i,j\)之间的 \(dis\) 置为 \(1\),可以用倍增 \(\text{Floyd}\) 实现。
然后直接 \(\text{Floyd}\) 最短路即可。

细节注意事项

  • 记得开\(\text{long long}\)

参考代码

#include <cstdio>
#define rg register
#define int long long 
const int MAXN = 55;
inline int min(int a, int b) { return a < b ? a : b; }
inline int read() {
	int s = 0; bool f = false; char c = getchar();
	while (c < '0' || c > '9') f |= (c =='-'), c = getchar();
	while (c >= '0' && c <= '9') s = (s << 3) + (s << 1) + (c ^ 48), c = getchar();
	return f ? -s : s;
}
bool g[MAXN][MAXN][70];
int dis[MAXN][MAXN];
signed main() {
	int n = read(), m = read();
	for (rg int i = 1; i <= n; ++i)
		for (rg int j = 1; j <= n; ++j)
			dis[i][j] = 0x7f7f7f7f;
	for (rg int i = 1; i <= m; ++i) {
		int u = read(), v = read();
		dis[u][v] = 1, g[u][v][0] = true;
	}
	for (rg int t = 1; t <= 64; ++t)
		for (rg int k = 1; k <= n; ++k)
			for (rg int i = 1; i <= n; ++i)
				for (rg int j = 1; j <= n; ++j)
					if (g[i][k][t - 1] && g[k][j][t - 1])
						g[i][j][t] = true, dis[i][j] = 1;
	for (rg int k = 1; k <= n; ++k)
		for (rg int i = 1; i <= n; ++i)
			for (rg int j = 1; j <= n; ++j)
				dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
	printf("%lld\n", dis[1][n]);
	return 0;
}

完结撒花 \(qwq\)

posted @ 2019-10-26 21:51  Sangber  阅读(114)  评论(0编辑  收藏  举报