【UVALive】6776 2014WorldFinal G Metal Processing Plant【2-sat——bitset优化kosaraju求scc】

题目链接:Metal Processing Plant

bitset优化kosaraju,复杂度O(n^2/64),总复杂度O(n^4/64)。

#include 
using namespace std ;

typedef long long LL ;
typedef pair < int , int > pii ;
typedef unsigned long long ULL ;

#define clr( a , x ) memset ( a , x , sizeof a )

const int MAXN = 205 ;
const int BLOCK = 4 ;
int LIM ;

struct Node {
    int v , x , y ;
    Node () {}
    Node ( int v , int x , int y ) : v ( v ) , x ( x ) , y ( y ) {}
    bool operator < ( const Node& a ) const {
        return v < a.v ;
    }
} ;

struct Bitset {
    ULL c[BLOCK] ;
    bool none () {
        for ( int i = 0 ; i < LIM ; ++ i ) {
            if ( c[i] ) return 0 ;
        }
        return 1 ;
    }
    void set () {
        for ( int i = 0 ; i < LIM ; ++ i ) {
            c[i] = ~0ULL ;
        }
    }
    void reset () {
        for ( int i = 0 ; i < LIM ; ++ i ) {
            c[i] = 0 ;
        }
    }
    void flip ( int x ) {
        c[x >> 6] ^= 1ULL << ( x & 63 ) ;
    }
    ULL& operator [] ( const int index ) {
        return c[index] ;
    }
} ;

Node a[MAXN * MAXN] ;
Bitset G[MAXN << 1] , V[MAXN << 1] , vis[2] ;
ULL pos[MAXN] , val[MAXN] ;
int scc[MAXN << 1] , scc_cnt ;
vector < int > S ;
int n , m ;

void add1 ( int x , int y ) {
    G[x << 1].flip ( y ) ;
    G[y << 1].flip ( x ) ;
    V[x << 1 | 1].flip ( y ) ;
    V[y << 1 | 1].flip ( x ) ;
}

void add2 ( int x , int y ) {
    G[x << 1 | 1].flip ( y ) ;
    G[y << 1 | 1].flip ( x ) ;
    V[x << 1].flip ( y ) ;
    V[y << 1].flip ( x ) ;
}

void dfs1 ( int u , int o ) {
    vis[o].flip ( u ) ;
    for ( int i = 0 ; i < LIM ; ++ i ) while ( 1 ) {
        ULL v = vis[o ^ 1][i] & G[u << 1 | o][i] ;
        if ( !v ) break ;
        dfs1 ( i << 6 | __builtin_ctzll ( v ) , o ^ 1 ) ;
    }
    S.push_back ( u << 1 | o ) ;
}

void dfs2 ( int u , int o ) {
    vis[o].flip ( u ) ;
    scc[u << 1 | o] = scc_cnt ;
    for ( int i = 0 ; i < LIM ; ++ i ) while ( 1 ) {
        ULL v = vis[o ^ 1][i] & V[u << 1 | o][i] ;
        if ( !v ) break ;
        dfs2 ( i << 6 | __builtin_ctzll ( v ) , o ^ 1 ) ;
    }
}

int check () {
    S.clear () ;
    vis[0].reset () ;
    vis[1].reset () ;
    for ( int i = 0 ; i < n ; ++ i ) {
        vis[0][pos[i]] |= val[i] ;
        vis[1][pos[i]] |= val[i] ;
    }
    for ( int o = 0 ; o < 1 ; ++ o ) {
        for ( int i = 0 ; i < LIM ; ++ i ) while ( vis[o][i] ) {
            dfs1 ( i << 6 | __builtin_ctzll ( vis[o][i] ) , o ) ;
        }
    }
    for ( int i = 0 ; i < n ; ++ i ) {
        vis[0][pos[i]] |= val[i] ;
        vis[1][pos[i]] |= val[i] ;
    }
    scc_cnt = 0 ;
    for ( int i = S.size () - 1 ; ~i ; -- i ) {
        int o = S[i] & 1 , x = S[i] >> 1 ;
        if ( vis[o][pos[x]] & val[x] ) {
            ++ scc_cnt ;
            dfs2 ( x , o ) ;
        }
    }
    for ( int i = 0 ; i < n ; ++ i ) {
        if ( scc[i << 1] == scc[i << 1 | 1] ) {
            return 0 ;
        }
    }
    return 1 ;
}

void solve () {
    m = 0 ;
    LIM = ( n - 1 ) / 64 + 1 ;
    for ( int i = 0 ; i < n ; ++ i ) {
        G[i << 1].reset () ;
        V[i << 1].reset () ;
        G[i << 1 | 1].reset () ;
        V[i << 1 | 1].reset () ;
        pos[i] = i >> 6 ;
        val[i] = 1ULL << ( i & 63 ) ;
    }
    for ( int i = 0 ; i < n ; ++ i ) {
        for ( int j = i + 1 , x ; j < n ; ++ j ) {
            scanf ( "%d" , &x ) ;
            a[++ m] = Node ( x , i , j ) ;
            add1 ( i , j ) ;
        }
    }
    sort ( a + 1 , a + m + 1 ) ;
    int ans = 2e9 + 10 ;
    for ( int i = 0 , j = m ; i <= j ; ++ i ) {
        while ( i && i <= j ) {
            add1 ( a[i].x , a[i].y ) ;
            if ( a[i].v != a[i + 1].v ) break ;
            ++ i ;
        }
        while ( i < j ) {
            add2 ( a[j].x , a[j].y ) ;
            if ( check () ) -- j ;
            else {
                add2 ( a[j].x , a[j].y ) ;
                break ;
            }
        }
        ans = min ( ans , a[i].v + a[j].v ) ;
    }
    printf ( "%d\n" , ans ) ;
}

int main () {
    while ( ~scanf ( "%d" , &n ) ) solve () ;
    return 0 ;
}

你可能感兴趣的:(2-sat,强连通【SCC】,双指针,bitset)