【HDU】5743 Join The Future【dp】

来源:互联网 发布:淘宝网妹儿粑粑饵料 编辑:程序博客网 时间:2024/06/05 17:08

题目链接:Join The Future

并查集压缩相等的点,发现最多只会有20个大于1的联通块,状压dp即可

#include <bits/stdc++.h>using namespace std ;typedef long long LL ;#define clr( a , x ) memset ( a , x , sizeof a )const int MAXN = 42 ;const int mod = 1e9 + 7 ;char buf[1000000] ;int len ;int p[MAXN] , c[MAXN] ;int L[MAXN] , R[MAXN] , odd[MAXN] , even[MAXN] ;int dp[MAXN][MAXN][2] ;pair < int , int > nxt[MAXN][MAXN][2] ;int ans[MAXN] , tmp[MAXN] ;int rt[MAXN] , col[MAXN] ;int idx[MAXN] ;int use[MAXN] ;int n , m ;int T ;int F ( int x ) {    if ( p[x] == x ) return x ;    int res = F ( p[x] ) ;    c[x] ^= c[p[x]] ;    return p[x] = res ;}int upd ( int x , int y , int o , int n ) {    if ( dp[y][x][o] == 0 ) return 0 ;    int m = y - x ;    for ( int i = x ; i <= y ; ++ i ) {        tmp[i] = nxt[y][i][o].first ;        o = nxt[y][i][o].second ;    }    return 1 ;}void up ( int ok ) {    if ( !ok ) return ;    for ( int i = 1 ; i <= n ; ++ i ) {        if ( tmp[i] > ans[i] ) return ;        if ( tmp[i] < ans[i] ) {            for ( int j = 1 ; j <= n ; ++ j ) {                ans[j] = tmp[j] ;            }            return ;        }    }}void add ( int x ) {    if ( x / 10 ) add ( x / 10 ) ;    buf[len ++] = x % 10 + '0' ;}void solve ( int Case ) {    scanf ( "%d%d" , &n , &m ) ;    for ( int i = 0 ; i <= n ; ++ i ) {        p[i] = i ;        c[i] = 0 ;        use[i] = 0 ;    }    for ( int i = 1 ; i <= n ; ++ i ) {        scanf ( "%d%d" , &L[i] , &R[i] ) ;        int tmp = R[i] - L[i] + 1 ;        odd[i] = tmp / 2 + ( tmp % 2 == 1 && R[i] % 2 == 1 ) ;        even[i] = tmp / 2 + ( tmp % 2 == 1 && R[i] % 2 == 0 ) ;    }    for ( int i = 1 ; i <= n ; ++ i ) {        for ( int j = 1 ; j <= n + 1 ; ++ j ) {            dp[i][j][0] = dp[i][j][1] = 0 ;            nxt[i][j][0] = make_pair ( mod , mod ) ;            nxt[i][j][1] = make_pair ( mod , mod ) ;        }    }    for ( int i = 1 ; i <= n ; ++ i ) {        dp[i][i + 1][0] = 1 ;        for ( int j = i ; j >= 1 ; -- j ) {            dp[i][j][0] = ( 1LL * dp[i][j + 1][1] * odd[j] + 1LL * dp[i][j + 1][0] * even[j] ) % mod ;            dp[i][j][1] = ( 1LL * dp[i][j + 1][0] * odd[j] + 1LL * dp[i][j + 1][1] * even[j] ) % mod ;        }        for ( int j = 1 ; j <= i ; ++ j ) {            if ( dp[i][j + 1][1] && odd[j] ) {                nxt[i][j][0] = min ( nxt[i][j][0] , make_pair ( L[j] + ( L[j] % 2 == 0 ) , 1 ) ) ;            }            if ( dp[i][j + 1][0] && even[j] ) {                nxt[i][j][0] = min ( nxt[i][j][0] , make_pair ( L[j] + ( L[j] % 2 == 1 ) , 0 ) ) ;            }            if ( dp[i][j + 1][0] && odd[j] ) {                nxt[i][j][1] = min ( nxt[i][j][1] , make_pair ( L[j] + ( L[j] % 2 == 0 ) , 0 ) ) ;            }            if ( dp[i][j + 1][1] && even[j] ) {                nxt[i][j][1] = min ( nxt[i][j][1] , make_pair ( L[j] + ( L[j] % 2 == 1 ) , 1 ) ) ;            }        }    }    int ok = 1 ;    for ( int i = 1 ; i <= m ; ++ i ) {        int u , v , w , x , y ;        scanf ( "%d%d%d" , &u , &v , &w ) ;        -- u ;        x = F ( u ) ;        y = F ( v ) ;        use[u] = use[v] = 1 ;        if ( x != y ) {            if ( x < y ) swap ( x , y ) ;            p[x] = y ;            c[x] = ( c[u] - c[v] + 2 + w ) % 2 ;        } else if ( ( c[u] ^ c[v] ) != w ) ok = 0 ;    }    if ( !ok ) {        buf[len ++] = '0' ;        buf[len ++] = '\n' ;        buf[len ++] = '-' ;        buf[len ++] = '1' ;        buf[len ++] = '\n' ;        return ;    }    int cnt = 0 , tot = 0 ;    for ( int i = 0 ; i <= n ; ++ i ) if ( use[i] ) {        if ( F ( i )  == i ) rt[cnt ++] = i ;        idx[tot ++] = i ;    }    int res = 0 , OK = 0 ;    for ( int i = 1 ; i <= n ; ++ i ) {        ans[i] = mod ;    }    for ( int s = 0 ; s < 1 << cnt ; ++ s ) {        if ( cnt && rt[0] == 0 && s % 2 ) continue ;        col[0] = 0 ;        for ( int i = 0 ; i < cnt ; ++ i ) {            col[rt[i]] = s >> i & 1 ;        }        int ans = 1 , j = 0 , ok = 1 ;        for ( int o = ( rt[0] == 0 ) ; o < tot ; ++ o ) {            int i = idx[o] , x = p[i] ;            if ( x != i ) col[i] = col[x] ^ c[x] ^ c[i] ;            ans = 1LL * ans * dp[i][j + 1][col[j] ^ col[i]] % mod ;            ok &= upd ( j + 1 , i , col[j] ^ col[i] , j ) ;            if ( !ok ) break ;            j = i ;        }        if ( ok && j < n ) {            ans = 1LL * ans * ( dp[n][j + 1][0] + dp[n][j + 1][1] ) % mod ;            int a = upd ( j + 1 , n , 0 , j ) ;            up ( ok && a ) ;            int b = upd ( j + 1 , n , 1 , j ) ;            up ( ok && b ) ;            ok &= a | b ;        } else up ( ok ) ;        if ( ok ) OK = 1 ;        res = ( res + ans ) % mod ;    }    if ( !OK ) {        buf[len ++] = '0' ;        buf[len ++] = '\n' ;        buf[len ++] = '-' ;        buf[len ++] = '1' ;        buf[len ++] = '\n' ;    } else {        add ( res ) ;        buf[len ++] = '\n' ;        for ( int i = 1 ; i <= n ; ++ i ) {            add ( ans[i] ) ;            buf[len ++] = i < n ? ' ' : '\n' ;        }    }}int main () {    //freopen ( "1010.in" , "r" , stdin ) ;    //freopen ( "1010.txt" , "w" , stdout ) ;    len = 0 ;    scanf ( "%d" , &T ) ;    for ( int i = 1 ; i <= T ; ++ i ) solve ( i ) ;    buf[len] = 0 ;    printf ( "%s" , buf ) ;    return 0 ;}
0 0
原创粉丝点击