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);
} 
posted @ 2020-10-23 19:05  INFP  阅读(98)  评论(0编辑  收藏  举报