把边按需求次数从小到大排序
然后快速幂+每次重构矩阵
#include <bits/stdc++.h>
using namespace std;
const int N=155;
bitset<N> tmp[N],cur[N],aa[N];
bitset<N> can[N],t,ok,mp[N];
int n,m;
void mat_p(int x){
for(int i=1;i<=n;i++){
cur[i]=mp[i];
aa[i].reset();
aa[i][i]=1;
}
while(x){
if(x&1){
for(int i=1;i<=n;i++)tmp[i].reset();
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(aa[i][j]){
tmp[i]|=cur[j];
}
}
}
for(int i=1;i<=n;i++){
aa[i]=tmp[i];
}
}
for(int i=1;i<=n;i++)tmp[i].reset();
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(cur[i][j]){
tmp[i]|=cur[j];
}
}
}
for(int i=1;i<=n;i++){
cur[i]=tmp[i];
}
x/=2;
}
}
struct Edge {
int u,v,w;
Edge(){}
Edge(int u,int v,int w):u(u),v(v),w(w){}
bool operator< (const Edge & th)const {
return w<th.w;
}
}e[N];
int main(){
#ifdef DouBi
freopen("input.cpp","r",stdin);
#endif // DouBi
while(scanf("%d%d",&n,&m)!=EOF){
for(int i=1;i<=m;i++){
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
}
sort(e+1,e+m+1);
e[0].w=0;
int flag=0;
can[0].reset();
can[0][1]=1;
for(int i=1;i<=n;i++){
mp[i].reset();
}
for(int i=1;i<=m&&!flag;i++){
mat_p(e[i].w-e[i-1].w);
can[i].reset();
for(int j=1;j<=n;j++){
if(can[i-1][j]){
can[i]|=aa[j];
}
}
ok=can[i];
mp[e[i].u][e[i].v]=1;
for(int j=0;j<n;j++){
if(ok[n]){
printf("%d\n",e[i].w+j);flag=1;break;
}
t.reset();
for(int k=1;k<=n;k++){
if(ok[k]){
t|=mp[k];
}
}
ok=t;
}
}
if(!flag){
printf("Impossible\n");
}
}
return 0;
}