CF780F
https://www.luogu.com.cn/problem/CF780F
看到路径类型都是\(2^i\),想到倍增
设\(f[0/1][s][u][v]\)表示从\(u\)到\(v\)存在一条以\(0/1\)开头,长度为\(2^s\)的路径
\(f[0/1][s][u][v]=f[0/1][s-1][u][v]~|~f[1/0][s-1][k][v]\)
可以\(bitset\)优化,计算答案时从长往短枚举,大于\(1e18\)就退出
int n,m,now; ll ans,Pow[100];
bitset<N>f[2][64][N],g,tmp;
int main(){
n = read(); m = read();int u,v,w;
for(int i = 1;i <= m;++i){
u = read(); v = read(); w = read();
f[w][0][u][v]=1;
}
for(int i = 1;i <= 60;++i)
for(int u = 1;u <= n;++u)
for(int v = 1;v <= n;++v){
if(f[0][i-1][u][v]) f[0][i][u] |= f[1][i-1][v];
if(f[1][i-1][u][v]) f[1][i][u] |= f[0][i-1][v];
}
if(f[0][60][1].count()){
puts("-1"); return 0;
}
now = 0; tmp[1] = 1; Pow[0] = 1;
for(int i = 1;i <= 60;++i) Pow[i] = Pow[i-1]<<1;
for(int i = 60;i >= 0;--i){
g.reset();
for(int j = 1;j <= n;++j)
if(tmp[j]) g |= f[now][i][j];
if(g.count()){
now ^= 1;tmp = g;
ans += Pow[i];
}
}
if(ans > inf) puts("-1");
else printf("%lld",ans);
}