Codeforces 576D Flights for Regular Customers(矩陣加速DP)
阿新 • • 發佈:2017-10-05
升序 str reg regular ++i http flight return 排序
題目鏈接 Flights for Regular Customers
首先按照d的大小升序排序
然後分成m個時刻,每條路徑一次處理過來。
can[i][j]表示當前時刻i能否走到j
can通過上一條路徑後的can和當前的可行路徑矩陣的d次冪得到。
這由floyd求解即可。考慮到d很大,用矩陣快速冪加速。
TLE on test 10
矩陣乘法的時候用bitset優化。
更新答案的時候,我們枚舉每個點。
若第1個點可以走到第i個點,則更新答案。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) const int N = 160; const int inf = 0x3f3f3f3f; int n, m, ans = inf; int dis[N][N], f[N][N]; int cnt; bitset <N> can[N], now[N], tmp[N], base[N]; struct node{ int x, y, d; void scan(){ scanf("%d%d%d", &x, &y, &d); } friend bool operator < (const node &a, const node &b){ return a.d < b.d; } } e[N]; void Mul(bitset<N> *a, bitset<N> *b){ bitset<N> ret[N]; rep(i, 1, n) rep(j, 1, n) if(a[i][j]) ret[i] |= b[j]; rep(i, 1, n) a[i] = ret[i]; } void Pow(bitset <N> *a, int b){ bitset <N> ret[N]; rep(i, 1, n) ret[i][i] = 1; for (; b; b >>= 1){ if (b & 1) Mul(ret, a); Mul(a, a); } rep(i, 1, n) a[i] = ret[i]; } int main(){ scanf("%d%d", &n, &m); rep(i, 1, m) e[i].scan(); sort(e + 1, e + m + 1); rep(i, 1, n) rep(j, 1, n) dis[i][j] = inf; rep(i, 1, n) dis[i][i] = 0; cnt = 0; ans = inf; rep(i, 1, n) can[i][i] = 1; rep(i, 1, m){ int x = e[i].x, y = e[i].y, d = e[i].d; rep(j, 1, n) tmp[j] = base[j]; Pow(tmp, d - cnt); Mul(can, tmp); rep(j, 1, n) rep(k, 1, n) dis[j][k] = min(dis[j][k], dis[j][x] + 1 + dis[y][k]); rep(j, 1, n - 1) if (can[1][j]) ans = min(ans, d + dis[j][n]); cnt = d; base[x][y] = 1; } if (ans < 0x3f3f3f3f) printf("%d\n", ans); else puts("Impossible"); return 0; }
Codeforces 576D Flights for Regular Customers(矩陣加速DP)