【代码】POJ 3678

来源:互联网 发布:unity3d文件如何运行 编辑:程序博客网 时间:2024/06/10 00:28
// 题目来源:POJ 3678// 题目大意:有很多点可取值0或1,它们之间有很多边为0或1,规定每条边由端点(xor,and,or)得到,求是否可行// 解决方法:每个点的取值只有两种情况,非常符合2-sat,用强连通分量判断即可// 特别注意:可通过在拆成的点对中搭边来保证最后的结果落在某个点上#include <cstdio>#include <string>#define o 1002#define _ 1000002void link( int, int );void tarjan( int );int next[ _*4 ], g[ _*4 ], h[ o*4 ], code[ o*4 ], dfn[ o*4 ], low[ o*4 ], stack[ o*4 ];int n, m, index, cnt, t, top;bool ins[ o*4 ];int main( ){    freopen( "3678.in", "r", stdin );    freopen( "3678.out", "w", stdout );    scanf( "%d%d", &n, &m );    int aa, bb, cc;    char st[ 10 ];    for( int i = 1; i <= m; i++ )    {        scanf( "%d%d%d%s", &aa, &bb, &cc, st );        if( strcmp( st, "AND" ) == 0 )            if( cc == 0 )            {                link( aa+n, bb );                link( bb+n, aa );            }            else            {                link( aa+n, bb+n );                link( bb+n, aa+n );                link( aa, aa+n );                link( bb, bb+n );            }        if( strcmp( st, "OR" ) == 0 )            if( cc == 0 )            {                link( aa, bb );                link( bb, aa );                link( aa+n, aa );                link( bb+n, bb );            }            else            {                link( aa, bb+n );                link( bb, aa+n );            }        if( strcmp( st, "XOR" ) == 0 )            if( cc == 0 )            {                link( aa, bb );                link( bb, aa );                link( aa+n, bb+n );                link( bb+n, aa+n );            }            else            {                link( aa, bb+n );                link( bb, aa+n );                link( aa+n, bb );                link( bb+n, aa );            }    }    for( int i = 0; i < 2*n; i++ )        if( !dfn[ i ] ) tarjan( i );    for( int i = 0; i < n; i++ )        if( code[ i ] == code[ i + n ] )        {            printf( "NO" );            return 0;        }    printf( "YES" );    return 0;}void link( int aa, int bb ){    next[ ++t ] = h[ aa ];    h[ aa ] = t;    g[ t ] = bb;}void tarjan( int i ){    int j;    dfn[ i ] = low[ i ] = ++index;    stack[ ++top ] = i;    ins[ i ] = 1;    for( int k = h[ i ]; k; k = next[ k ] )    {        j = g[ k ];        if( !dfn[ j ] )        {            tarjan( j );            if( low[ j ] < low[ i ] ) low[ i ] = low[ j ];        }        else if( ins[ j ] && dfn[ j ] < low[ i ] )            low[ i ] = dfn[ j ];    }    if( dfn[ i ] == low[ i ] )    {        cnt++;        do        {            j = stack[ top-- ];            code[ j ] = cnt;            ins[ j ] = 0;        }        while( i != j );    }}