[洛谷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 }

猜你喜欢

转载自www.cnblogs.com/ac-evil/p/10335216.html
今日推荐