[luogu1613]跑路

题意

Here

思考

跑最短路再判定肯定是错的,我们可以这样做:用 \(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;
}

猜你喜欢

转载自www.cnblogs.com/alecli/p/9900843.html