本题目的意思是给定了一个有向图,n个点,m条变,n<=150,每个边上还有一个d值代表已经经过了d条边这条边才能够走,那么求最少要经过多少条边才能从1出发走到n
解析:
用一个矩阵A(1,n) 代表当前该人走了固定步数可以到达的点,0代表不可以到达,1反之。
用一个B(n,n)代表当前的转移矩阵,即那些边是可以走的,那么把所有边按照d排序,那么在下一条边可以走之前,必须先由现在可达的状态至少再走差值步数,如果走了小于等于差值步数到达了n,那么只需在原来没走差值步的基础上枚举走几步可到达即可。
为了表示 “走了小于等于差值步数到达了n”初始B的n -> n为 1 代表可以在n这个地方逗留。
下面的模板用的是anta的,
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <set> #include <map> #include <string> #include <list> #include <cstdlib> #include <queue> #include <stack> #include <cmath> #include <bitset> #include <cassert> #define ALL(a) a.begin(), a.end() #define clr(a, x) memset(a, x, sizeof a) #define fst first #define snd second #define pb push_back #define lowbit(x) (x&(-x)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define rep1(i,x,y) for(int i=x;i<=y;i++) #define rep(i,n) for(int i=0;i<(int)n;i++) using namespace std; const double eps = 1e-10; typedef long long LL; typedef long long ll; typedef pair<int, int> pii; const int oo =0x3f3f3f3f; typedef bitset<160> BitSet; struct Matrix { int wid; vector<BitSet> v, w; Matrix(): wid(0) {} Matrix(int n, int m): v(n, BitSet()), wid(m) { } inline int height() const { return (int)v.size(); } inline int width() const { return wid; } inline bool at(int i, int j) const { return v[i][j]; } static Matrix identity(int n) { Matrix A(n, n); rep(i, n) A.v[i][i] = 1; return A; } inline static Matrix identity(const Matrix& A) { return identity(A.height()); } vector<BitSet> trans() const { int n = height(), m = width(); vector<BitSet> res(m, BitSet()); rep(i, n) rep(j, m) res[j][i] = v[i][j]; return res; } Matrix& operator*=(const Matrix& B) { int n = height(), m = B.width(), p = B.height(); vector<BitSet> transB = B.trans(); assert(p == width()); w.assign(n, BitSet()); rep(i, n) rep(j, m) w[i][j] = (v[i] & transB[j]).any(); v.swap(w); return *this; } void show(){ cout<<"--------------------\n"; rep(i,height()){ rep(j,width()) cout<<v[i][j]<<" "; cout<<endl; } } }; Matrix operator^(const Matrix& t, ll k) { Matrix A = t, B = Matrix::identity(t); while(k) { if(k & 1) B *= A; A *= A; k >>= 1; } return B; } struct node{ int u,v,d; node(int u=0,int v=0,int d=0):u(u),v(v),d(d){} bool operator<(const node& rhs)const{ return d < rhs.d; } }; int n,m; vector<node> st; int main() { scanf("%d %d",&n,&m); rep(i,m){ int x,y,z; scanf("%d %d %d",&x,&y,&z); x--; y--; st.push_back(node(x,y,z)); } sort(st.begin(),st.end()); Matrix A(n,n); A.v[n-1][n-1]=1; Matrix ans(1,n); ans.v[0][0]=1; int pred = 0 , res = -1; rep(i,st.size()+1){ node te; if(i < st.size()) te = st[i]; int k = (i == st.size() ? n : te.d - pred); Matrix cc = ans; ans*=A^k; if(ans.v[0][n-1]){ for(int j=1;j<=n;j++){ cc*=A; if(cc.v[0][n-1]){ res = pred + j; break; } } break; } if(i == st.size()) break; A.v[te.u][te.v] = 1; pred = te.d; } if(res == -1) printf("Impossible\n"); else printf("%d\n",res); return 0; }