【代码】POJ 3648

// 题目来源:POJ 3648
// 题目大意:有n对夫妻参加婚礼,现安排座位,已经某些人不能同时坐在新娘的对面,且夫妻不可同侧,求可行方案
// 解决方法:仍然2-sat建图解决
// 特别注意:新娘到新郎要连边,因为选出的必须是新郎

#include <cstdio>
#include <string>
#define o 100000
#define _ 1000000
using namespace std;

void link( int, int );
void link2( int, int );
void tarjan( int );
void topsort( int );
void dfs( int );

int next[_], next2[_], g[_], g2[_];
int h[o], h2[o], dfn[o], low[o], stack[o], done[o], code[o], color[o], cfl[o], id[o];
int n, m, top, t, t2, tt, index, cnt;
bool ins[o];
bool ok;

int main( )
{
    freopen( "3648.in", "r", stdin );
    freopen( "3648.out", "w", stdout );
    scanf( "%d%d", &n, &m );
    int aa, bb;
    char ch, ch2;
    while( n != 0 )
    {
        memset( next, 0, sizeof( next ) );
        memset( next2, 0, sizeof( next2 ) );
        memset( h, 0, sizeof( h ) );
        memset( h2, 0, sizeof( h2 ) );
        memset( dfn, 0, sizeof( dfn ) );
        memset( low, 0, sizeof( low ) );
        memset( code, 0, sizeof( code ) );
        memset( color, 0, sizeof( color ) );
        memset( id, 0, sizeof( id ) );
        memset( cfl, 0, sizeof( cfl ) );
        t = t2 = tt = index = cnt = 0;
        ok = true;
        while( m-- )
        {
            scanf( "%d%c%d%c", &aa, &ch, &bb, &ch2 );
            aa *= 2;
            if( ch == 'w' ) aa ^= 1;
            bb *= 2;
            if( ch2 == 'w' ) bb ^= 1;
            link( aa, bb^1 );
            link( bb, aa^1 );  
        }
        link( 1, 0 );
        for( int i = 0; i < 2*n; i++ )
            if( !dfn[i] ) tarjan( i );
        for( int i = 0; i < 2*n; i++ )
            if( code[i] == code[i^1] )
            {
                printf( "bad luck\n" );
                ok = false;
                break;
            }
        if( ok )
        {
            for( int i = 0; i < 2*n; i++ )
            {
                for( int k = h[i]; k; k = next[k] )
                {
                    int j = g[k];
                    if( code[i] == code[j] ) continue;
                    link2( code[j], code[i] );
                    id[ code[i] ]++;
                }
                cfl[ code[i] ] = code[i^1];
                cfl[ code[i^1] ] = code[i];
            }
            for( int i = 1; i <= cnt; i++ )
                if( id[i] == 0 ) topsort( i );
            for( int ii = 1; ii <= cnt; ii++ )
            {
                int i = done[ii];
                if( color[i] != 0 ) continue;
                color[i] = 1;
                dfs( cfl[i] );
            }
            for( int i = 2; i < 2*n; i++ )
                if( color[ code[i] ] == 2 )
                    if( ( i & 1 ) == 0 )
                        printf( "%dh ", i/2 );
                    else
                        printf( "%dw ", i/2 );
            printf( "\n" );
        }
        scanf( "%d%d", &n, &m );
    }
}

void link( int aa, int bb )
{
    next[++t] = h[aa];
    h[aa] = t;
    g[t] = bb;
}

void link2( int aa, int bb )
{
    next2[++t2] = h2[aa];
    h2[aa] = t2;
    g2[t2] = bb;
}

void tarjan( int i )
{
    int j;
    dfn[i] = low[i] = ++index;
    stack[++top] = i;
    ins[i] = true;
    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--];
            ins[j] = false;
            code[j] = cnt;
        }
        while( i != j );
    }
}

void topsort( int i )
{
    int j;
    id[i] = -1;
    done[++tt] = i;
    for( int k = h2[i]; k; k = next2[k] )
    {
        j = g2[k];
        id[j]--;
        if( id[j] == 0 ) topsort( j );
    }
}

void dfs( int i )
{
    int j;
    color[i] = 2;
    for( int k = h2[i]; k; k = next2[k] )
    {
        j = g2[k];
        if( color[j] == 0 ) dfs( j );
    }
}

猜你喜欢

转载自blog.csdn.net/JarjingX/article/details/8518514