@codeforces - 781D@ Axel and Marston in Bitland


@description@

經過如下的方法生成一個序列:
(1)初始時只有一個 "P"。
(2)將當前字符串 s 的 "P" 變成 "B","B" 變成 "P" 獲得 s',將 s' 接在 s 以後獲得新的序列。
生成的前幾個步驟獲得字符串爲 P,PB,PBBP,PBBPBPPB......優化

給定一個有向圖,每條邊上有字符 'P' 或者 'B'。求從點 1 出發走出如上序列的最長路徑(即第一步走 s[1], 第二步走 s[2], ...)的最長可能長度。
若是長度 > 10^18,則輸出 -1。ui

Input
第一行兩個整數 n, m (1 ≤ n ≤ 500, 0 ≤ m ≤ 2n^2),表示點數與邊數。
接下來 m 行,第 i 行三個整數 vi, ui, ti (1 ≤ vi, ui ≤ n, 0 ≤ ti ≤ 1), 表示一條 vi -> ui 的有向邊。0 表示 'P',1 表示 'B'。保證無重邊,但可能有自環。
Output
若是最長可能長度 > 10^18,輸出 -1;不然輸出最長可能長度。spa

@solution@

對於前 2^i 個字符,咱們能夠看做先走前 2^(i-1) 個字符,再走後 2^(i-1) 個字符(廢話)。code

同時維護兩個東西,一個是題目所說的 PBBPBPPB... 類型的路徑 s1,另外一個是取反事後的 BPPBPBBP... 類型的路徑 s2。
從 2^(i-1) 轉移到 2^i,有 s1' = s1 + s2,s2' = s2 + s1。ip

記 f[0/1][i][x][y],0/1 表示是第一類仍是第二類,從 x 出發走 2^i 步是否能夠到達 y。
轉移時枚舉中轉點,從 f[0][i-1][x][z] 與 f[1][i-1][z][y] 轉移到 f[0][i][x][y],從 f[1][i-1][x][z] 與 f[0][i-1][z][y] 轉移到 f[1][i][x][y]。
最後求出 i = 0...60 對應的 f,利用倍增的思想獲得最長可能長度(這裏的過程相似於倍增求樹上 lca 的過程)。
這個複雜度爲 O(n^3*logA),其中 A = 10^18。字符串

注意到這個其實就像一個 Floyd 傳遞閉包,而衆所周知這個東西是能夠用 bitset 優化的,並且效果還很明顯。
那麼使用 bitset 事後,複雜度被優化成 O(n^3*logA / w),其中 w = 32 或 64。it

@accepted code@

#include <cstdio>
#include <bitset>
using namespace std;
bitset<500>bts[2][61][500], nw, tmp;
int main() {
    int n, m; scanf("%d%d", &n, &m);
    for(int i=1;i<=m;i++) {
        int u, v, p; scanf("%d%d%d", &u, &v, &p), u--, v--;
        bts[p][0][u].set(v, 1);
    }
    for(int p=1;p<=60;p++) {
        for(int k=0;k<n;k++)
            for(int i=0;i<n;i++) {
                if( bts[0][p-1][i][k] ) bts[0][p][i] |= bts[1][p-1][k];
                if( bts[1][p-1][i][k] ) bts[1][p][i] |= bts[0][p-1][k];
            }
    }
    int type = 0; nw.set(0, 1);
    long long ans = 0;
    for(int i=60;i>=0;i--) {
        tmp = 0;
        for(int j=0;j<n;j++)
            if( nw[j] && bts[type][i][j].any() )
                tmp |= bts[type][i][j];
        if( tmp.any() ) {
            ans |= (1LL<<i);
            type ^= 1, nw = tmp;
        }
    }
    if( ans > (long long)(1E18) ) puts("-1");
    else printf("%lld\n", ans);
}

@details@

bitset 真好用.jpg。io

相關文章
相關標籤/搜索