1. 程式人生 > >[洛谷P1613]跑路

[洛谷P1613]跑路

-- print register urn gin mes con using eof

題目傳送門

這道題題意不是很清楚。在翻看了幾個討論後,理清了題意。

這道題有環,有重邊,甚至可能一次性到終點,而整段路線繞著某個環跑好多圈。每次跳必須要到一個點。

然後這道題要倍增,來判斷從一個點是否能一次到另一個點。

所以設$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 }

[洛谷P1613]跑路