本题目的意思是给定了一个有向图,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;
}