// 题目来源:POJ 3207
// 题目大意:圆上顺序排列n个点,现要在一些点间连边,规定边只能在圆内或圆外,求有没有可能不相交
// 解决方法:连边只能在里面或者外面,这就是2-sat问题,直接缩点判断即可
#include <cstdio>
#define o 5002
void link( int, int );
void tarjan( int );
int next[ o ], h[ o ], g[ o ], a[ o ], b[ o ], code[ o ], dfn[ o ], low[ o ], stack[ o ];
int n, m, t, top, index, cnt, i = 0, j;
bool ins[ o ];
int main( )
{
freopen( "3207.in", "r", stdin );
freopen( "3207.out", "w", stdout );
scanf( "%d%d", &n, &m );
for( int i = 0; i <= m-1; i++ )
{
scanf( "%d%d", &a[ i ], &b[ i ] );
if( a[ i ] > b[ i ] )
{
int temp = a[ i ];
a[ i ] = b[ i ];
b[ i ] = temp;
}
}
for( int i = 0; i <= m-1; i++ )
for( int j = i + 1; j <= m-1; j++ )
if( a[ i ] < a[ j ] && b[ i ] > a[ j ] && b[ i ] < b[ j ] || b[ i ] > b[ j ] && a[ i ] > a[ j ] && a[ i ] < b[ j ] )
{
link( i*2, j*2+1 );
link( i*2+1, j*2 );
link( j*2, i*2+1 );
link( j*2+1, i*2 );
}
for( int i = 0; i <= 2*m-1; i++ )
if( !dfn[ i ] ) tarjan( i );
for( int i = 0; i <= 2*m-1; i++ )
if( code[ i ] == code[ i^1 ] )
{
printf( "the evil panda is lying again" );
return 0;
}
printf( "panda is telling the truth..." );
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 ] )
if( dfn[ j ] < low[ i ] ) low[ i ] = dfn[ j ];
}
if( low[ i ] == dfn[ i ] )
{
cnt++;
do
{
j = stack[ top-- ];
code[ j ] = cnt;
ins[ j ] = 0;
}
while( i != j );
}
}
【代码】POJ 3207
最新推荐文章于 2018-10-09 19:32:46 发布