[洛谷P1613]跑路
题目传送门
这道题题意不是很清楚。在翻看了几个讨论后,理清了题意。
这道题有环,有重边,甚至可能一次性到终点,而整段路线绕着某个环跑好多圈。每次跳必须要到一个点。
然后这道题要倍增,来判断从一个点是否能一次到另一个点。
所以设$e[i][j][k]$表示从第$i$个点是否存在一条路径长为$2^k$到点$j$。
更新跟$Floyd$很相像,若$e[i][p][k-1] \ \&\&\ e[p][j][k-1]$为$1$,则$e[i][j][k]$为1。
然后点$i$到点$j$能否直接跳达就转变成$e[i][j][1..32]$中是否有1。设成$32$是因为$2^32$符合题意$maxlongint$。
构图跑最短路即可。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define re register 6 #define rep(i, a, b) for (re int i = a; i <= b; ++i) 7 #define repd(i, a, b) for (re int i = a; i >= b; --i) 8 #define maxx(a, b) a = max(a, b); 9 #define minn(a, b) a = min(a, b); 10 #define LL long long 11 #define inf (1 << 30) 12 13 const int maxn = 50 + 5, maxk = 35; 14 15 inline int read() { 16 int w = 0, f = 1; char c = getchar(); 17 while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar(); 18 while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar(); 19 return w * f; 20 } 21 22 int n, m, e[maxn][maxn][maxk]; 23 LL E[maxn][maxn]; 24 25 int main() { 26 n = read(); m = read(); 27 memset(e, sizeof(e), 0); 28 memset(E, sizeof(E), 0); 29 rep(i, 1, m) { 30 int u = read(), v = read(); 31 e[u][v][0] = 1; 32 } 33 rep(k, 1, maxk - 1) 34 rep(p, 1, n) 35 rep(i, 1, n) 36 rep(j, 1, n) 37 e[i][j][k] |= e[i][p][k-1] & e[p][j][k-1]; 38 39 rep(i, 1, n) 40 rep(j, 1, n) { 41 rep(k, 0, maxk - 1) 42 E[i][j] |= e[i][j][k]; 43 E[i][j] = E[i][j] ? 1 : (1LL << 40); 44 } 45 46 rep(k, 1, n) 47 rep(i, 1, n) 48 rep(j, 1, n) 49 if (i != k && j != k) 50 minn(E[i][j], E[i][k] + E[k][j]); 51 52 printf("%lld", E[1][n]); 53 return 0; 54 }