题目大意
给出一张有向图,对于边
i
有限制条件
题解
比较容易想到的暴力是
fi,j
表示在走
j
步能不能正好到
这种做法在
di
很小的时候才可以通过。所以说貌似没什么用。
考虑以前DNA Sequence这类题目用到过的思路,邻接矩阵的
k
次方等于
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];
}
bitset<N> a[N], b[N];
mul(a, b);
思路是,如果
在枚举边的时候通过
#include<bits/stdc++.h>
using namespace std;
using std::bitset;
#define rep(i, l, r) for(register int i = (l); i <= (r); i++)
const int N = 150 + 10, inf = 0x7fffffff;
int n, m, ans;
int d[N][N];
struct Edge{
int u, v, w;
bool operator < (const Edge &rhs) const{
return w < rhs.w;
}
}edg[N];
bitset<N> ari[N], g[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 poww(bitset<N> *a, int k){
bitset<N> ret[N];
rep(i, 1, n) ret[i][i] = 1;
while(k){
if(k & 1) mul(ret, a);
mul(a, a);
k >>= 1;
}
rep(i, 1, n) a[i] = ret[i];
}
void work(){
bitset<N> tmp[N];
int now = 0; ans = inf;
memset(d, 0x3f, sizeof(d));
for(int i = 1; i <= n; i++) d[i][i] = 0, ari[i][i] = 1;
rep(i, 1, m){
int u = edg[i].u, v = edg[i].v, w = edg[i].w;
rep(j, 1, n) rep(k, 1, n)
d[j][k] = min(d[j][k], d[j][u] + 1 + d[v][k]);
rep(j, 1, n) tmp[j] = g[j];
poww(tmp, w - now);
mul(ari, tmp);
rep(j, 1, n)
if(ari[1][j] && d[j][n] != 1061109567){
ans = min(ans, w + d[j][n]);
}
now = w;
g[u][v] = 1;
}
if(ans == inf) puts("Impossible");
else printf("%d\n", ans);
}
void init(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++)
scanf("%d%d%d", &edg[i].u, &edg[i].v, &edg[i].w);
sort(edg + 1, edg + m + 1);
}
int main(){
init();
work();
return 0;
}