[luogu1613]跑路
阿新 • • 發佈:2018-11-03
題意
思考
跑最短路再判定肯定是錯的,我們可以這樣做:用 \(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; }