Codeforces 781D Axel and Marston in Bitland 矩陣 bitset
阿新 • • 發佈:2018-10-27
多少 tchar 當前 digi con names include [1] ORC
原文鏈接https://www.cnblogs.com/zhouzhendong/p/CF781D.html
題目傳送門 - CF781D
題意
有一個 n 個點的圖,有 m 條有向邊,邊有兩種類型:0 和 1 。
有一個序列,其構造方案為:初始情況為 0 ;對於當前串,將當前串的 0 變成 1 ,1 變成 0 ,接到當前串的後面,得到一個新串;不斷進行這個操作。
最終得到一個形如 0110100110010110…… 的無限串。
問從節點 1 出發,依次經過上述串對應的 0/1 邊,最多能走多少步。
如果答案大於 $10^{18}$ ,輸出 -1 。
$n\leq 500,m\leq 2n^2$
題解
首先考慮處理出兩個矩陣,分別處理 0/1 兩種類型的邊的轉移。
於是我們可以直接矩陣倍增一下得到一個 $O(n^3 \log 10^{18})$ 的做法。
再註意到我們只關系這些矩陣元素是否為 0 ,那麽我們只需要用 bitset 優化一下矩陣乘法就好了。
時間復雜度 $O(n^3 \log 10^{18} / 32)$ 。
代碼
#include <bits/stdc++.h> using namespace std; typedef long long LL; LL read(){ LL x=0,f=1; char ch=getchar(); while (!isdigit(ch)&&ch!=‘-‘) ch=getchar(); if (ch==‘-‘) f=-1,ch=getchar(); while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return x*f; } const int N=505; const LL INF=1000000000000000000LL; int n,m; struct Mat{ bitset <N> v[N]; Mat(){} Mat(int x){ for (int i=1;i<=n;i++) v[i].reset(); for (int i=1;i<=n;i++) v[i][i]=x; } friend Mat operator * (Mat a,Mat b){ Mat ans(0); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if (a.v[i][j]) ans.v[i]|=b.v[j]; return ans; } }M[2][35]; int main(){ n=read(),m=read(); M[0][0]=M[1][0]=Mat(0); for (int i=1;i<=m;i++){ int a=read(),b=read(),t=read(); M[t][0].v[a][b]=1; } int k=0; while (M[0][k].v[1].count()&&(1LL<<(k<<1))<=INF){ k++; M[0][k]=M[0][k-1]*M[1][k-1]*M[1][k-1]*M[0][k-1]; M[1][k]=M[1][k-1]*M[0][k-1]*M[0][k-1]*M[1][k-1]; } LL s=0,p=0; Mat now(0); now.v[1][1]=1; while (k>0&&s<=INF){ k--; if ((now*M[p][k]).v[1].count()){ now=now*M[p][k]; s+=1LL<<(k<<1); p^=1; if ((now*M[p][k]).v[1].count()){ now=now*M[p][k]; s+=1LL<<(k<<1); if ((now*M[p][k]).v[1].count()){ now=now*M[p][k]; s+=1LL<<(k<<1); p^=1; } } } } if (s>INF) puts("-1"); else cout << s << endl; return 0; }
Codeforces 781D Axel and Marston in Bitland 矩陣 bitset