临接矩阵的 k 次 就是 恰好 走 k 步从 i 走到 j 的方案数, 方案数在这里并不关键, 所以可以把它变成01矩阵。
一个很直观的想法是用二分取check它, 但是这并不单调。。 然后就不会了。。
我们可以把G[ n - 1] [ n - 1 ] 变成 1 , 这个函数就变成单调了, 然后直接二分check就好了, 可以用bitset优化一下, 不优化其实也能过。
还有一种方法就是, 每新加入一条边, 我们暴力跑一遍图取check就好啦。
#include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ALL(x) (x).begin(), (x).end() #define fio ios::sync_with_stdio(false); cin.tie(0); using namespace std; const int N = 150 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-8; const double PI = acos(-1); template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;} template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;} template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;} template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;} const int MN = 150; struct Matrix { bitset<MN> a[MN]; void init() { for(int i = 0; i < MN; i++) a[i][i] = 1; } void setVal(int c[MN][MN]) { for(int i = 0; i < MN; i++) for(int j = 0; j < MN; j++) a[i][j] = c[i][j]; } Matrix operator * (const Matrix& B) const { Matrix C; for(int i = 0; i < MN; i++) for(int j = 0; j < MN; j++) if(a[i][j]) C.a[i] |= B.a[j]; return C; } Matrix operator ^ (LL b) { Matrix C; C.init(); Matrix A = *this; while(b) { if(b & 1) C = C * A; A = A * A; b >>= 1; } return C; } } mat[N], now[N], tmp; int n, m, a[N], b[N], d[N]; int G[MN][MN]; vector<int> oo; vector<PII> edge[N]; int main() { scanf("%d%d", &n, &m); for(int i = 0; i < m; i++) { scanf("%d%d%d", &a[i], &b[i], &d[i]); a[i]--; b[i]--; oo.push_back(d[i]); } oo.push_back(0); sort(ALL(oo)); oo.erase(unique(ALL(oo)), oo.end()); for(int i = 0; i < m; i++) { edge[lower_bound(ALL(oo), d[i]) - oo.begin()].push_back(mk(a[i], b[i])); } tmp.init(); int p = SZ(oo) - 1; G[n - 1][n - 1] = 1; for(int i = 0; i < SZ(oo); i++) { now[i] = tmp; if(now[i].a[0][n - 1]) { p = i - 1; break; } for(auto& e : edge[i]) { G[e.fi][e.se] = 1; } mat[i].setVal(G); if(i == SZ(oo) - 1) break; tmp = tmp * (mat[i] ^ (oo[i + 1] - oo[i])); } Matrix gg; int low = 1, high = p == SZ(oo) - 1 ? 1000000200 : oo[p + 1] - oo[p], mid, step = -1; while(low <= high) { mid = low + high >> 1; gg = now[p] * (mat[p] ^ mid); if(gg.a[0][n - 1]) high = mid - 1, step = mid; else low = mid + 1; } if(~step) printf("%d ", oo[p] + step); else puts("Impossible"); return 0; } /* */