「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\)

猜你喜欢

转载自www.cnblogs.com/zsbzsb/p/11745754.html